关于Java中Synchronized互斥范围小结

Synchronized的使用比较简单,就是对代码进行同步。但是昨天在看书的时候发现了一个比较困惑的地方,就是类和实例对象之间的同步。有以下几种情况

1.静态方法间的同步即对类对象进行同步,线程对test1和test2方法的访问是互斥的

static synchronized void test1() {
    System.out.println(" test1");		
}
static synchronized void test2() {
    System.out.println(" test2");
}

2.实例方法间的同步即对实例对象进行同步,线程对同一对象的test1和test2方法的访问是互斥的,但是不同实例对象各自调用的话由于锁住的不同的实例对象,所以test1和test2是不互斥的。

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService pool = Executors.newFixedThreadPool(2);
        TestSynchronized test = new TestSynchronized();
        pool.execute(new Runnable() {            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                //test.test1(); //互斥
                new TestSynchronized().test1(); //不互斥 因为锁加在不同的实例对象上
            }
        });
        pool.execute(new Runnable() {            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                //TestSynchronized.test2();
                //test.test2(); //互斥
                new TestSynchronized().test2();//不互斥,锁加在不同的对象上

        }

        });
        pool.shutdown();
    }
       

  synchronized void test1() {
     System.out.println(" test1");	
     try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
  }
  synchronized void test2() {
     System.out.println(" test2");
     try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 }

以上都比较好理解,但是如果是下面这种情况,会怎么样呢?静态方法会和实例方法互斥吗?

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService pool = Executors.newFixedThreadPool(2);
        TestSynchronized test = new TestSynchronized();
        pool.execute(new Runnable() {            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                TestSynchronized.test1();
            }
        });
        pool.execute(new Runnable() {            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                test.test2();
            }
        });
        pool.shutdown();
    }
        synchronized void test1() {
	    System.out.println(" test1");		
            try {
            Thread.sleep(5000);
            } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }
	}
	void test2() {
	    System.out.println(" test2");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
//程序会同时输出test1和test2

答案是不会的,程序会同时输出test1和test2,我的理解是静态方法调用时候锁住的是类对象,也就是存在方法区中的那个,而实例方法调用时候锁住的是实例对象本身,二者并不存在互斥关系。

所以说如果锁住的是类对象,也就是调用静态同步方法或者是synchronized(类.class)同步块的时候,那么有关类对象的同步调用就存在互斥关系,如果锁住的是同一个实例对象,也就是调用同一实例对象的同步方法或者synchronized(this)同步块的时候,则同一实例对象的同步调用存在互斥关系。类对象的同步和实例对象的同步由于锁的是不同对象,所以不存在互斥关系。














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值