java中synchronized理解与使用

1.同步锁的基本理解

当synchronized锁住一个对象后,别的线程如果也想拿到这个对象的锁,就必须等待这个线程执行完成释放锁,才能再次给对象加锁,这样才达到线程同步的目的。即使两个不同的代码段,都要锁同一个对象,那么这两个代码段也不能在多线程环境下同时运行。

2.使用时要明白两个问题

  • 锁的对象是谁
  • 锁当前的持有者

举例子说明:
例一:

public class Test {

    public synchronized void methodA(String param) {
        System.out.println("methodA's param :" + param);
    }

    public synchronized void methodB(){
        methodA("methodB");
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.methodB();
    }
}

执行结果:

methodA’s param :methodB invoke

分析:
① methodB被调用因为有synchronized需要获得一个锁,锁的对象是test,也就是当前Test类的实例,而获得所得东西是线程,也就是当前线程拿到了test的锁(不是B方法获得了锁)
② methodB内部调用了methodA,此时A也加了synchronized,也需要获得一个锁,因为A和B都是Test类中的方法,所以当前线程要获得的锁的对象也是test,而当前线程执行B方法时已经持有了test对象的锁,所以会直接调用methodA,相当于方法A上没有加synchronized。

例二:

public class Test {

    public synchronized void methodA(String param) {
        System.out.println("methodA's param :" + param);
    }

    public synchronized void methodB(){
        methodA("methodB");
    }

    public static void main(String[] args) {
        Test test1 = new Test();
        Test test2 = new Test();
        test1.methodB();
        test2.methodB();
    }
}

运行结果:

methodA’s param :methodB
methodA’s param :methodB

分析:
① 执行test1.methodB()当前线程会持有test1对象的锁
② 执行test2.methodB()当前线程会持有test2对象的锁
③ 当前线程持有了两把锁,但是锁的对象不一样,所以互相没有影响

例三:

public class Test {

    public synchronized void methodA(String param) {
        System.out.println("methodA's param :" + param);
    }

    public synchronized void methodB(){
        methodA("methodB");
    }

    public static void main(String[] args) {
        Test test = new Test();
        ThreadTest thread1 = test.new ThreadTest("thread1");
        ThreadTest thread2 = test.new ThreadTest("thread2");
        thread1.start();
        thread2.start();
    }

    class ThreadTest extends Thread {

        public ThreadTest(String name){
            super(name);
        }

        public void run() {
            Test test = new Test();
            test.methodB();
        }
    }
}

运行结果:

methodA’s param :methodB
methodA’s param :methodB

分析:

① thread1先获取test的锁
② thread1执行methodB
③ thread1执行methodA
④ thread1释放test的锁
⑤ thread2获得test的锁
⑥ thread2执行methodB
⑦ thread2执行methodA
⑧ thread2释放test的锁

总结:例三和例二结果一样,但是执行顺序却不同,另外synchronized还有很多种用法,在分析时一定要搞清楚哪个线程获得了哪个对象的锁,就很容易明白了。

猜你喜欢

转载自blog.csdn.net/jianiuqi/article/details/53448941
今日推荐