synchronized锁住的是代码仍是对象

不一样的对象

public class Sync {
    public synchronized void test() {
        System.out.println("test start");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("test end");
    }
}

#html

public class MyThread extends Thread{
    public void run() {
        Sync sync = new Sync();
        sync.test();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread();
            thread.start();
        }
    }
}

执行结果程序员

test start
test start
test start
test end
test end
test end  

现象swift

在MyThread中,每次都new一个新的Sync对象,能够看到代码块test虽然被加了synchonized可是仍是并行执行的,初步结论:锁住的不是代码块安全

同一个对象

public class MyThread2 extends Thread{
    public Sync sync;
    MyThread2(Sync sync) {
        this.sync = sync;
    }

    public void run() {
        System.out.println("hi....");
        sync.test();
    }

    public static void main(String[] args) {
        Sync sync = new Sync();
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread2(sync);
            thread.start();
        }
    }

执行结果bash

hi....
test start
hi....
hi....
test end
test start
test end
test start
test end  

现象并发

能够看到当他们共用一个对象的时候,synchonized起了做用,这块代码是串行执行的性能

结论

锁住的是对象this

如何在多对象的时候任然锁住代码?

解决也很简单,只要锁住同一个对象就好了。例如:synchronized后的括号中锁同一个固定对象,这样就好了。spa

这样是没问题,可是,比较多的作法是让synchronized锁这个类对应的Class对象。.net

public class Sync2 {
    public void test() {
        synchronized (Sync2.class) {
            System.out.println("test start");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("test end");
        }
    }
}

#

public class MyThread3 extends Thread{
    public void run() {
        Sync2 sync = new Sync2();
        sync.test();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread3();
            thread.start();
        }
    }
}

执行结果

test start
test end
test start
test end
test start
test end

synchronized的两大不足

  • 因为咱们没办法设置synchronized关键字在获取锁的时候等待时间,因此synchronized可能会致使线程为了加锁而无限期地处于阻塞状态
  • 使用synchronized关键字等同于使用了互斥锁,即其余线程都没法得到锁对象的访问权。这种策略对于读多写少的应用而言是很不利的,由于即便多个读者看似能够并发运行,但他们实际上仍是串行的,并将最终致使并发性能的降低。 

虽然synchronized已经做为一个关键字被固化在Java语言中了,但它只提供了一种至关保守的线程安全策略,且该策略开放给程序员的控制能力极弱

参考

synchonized控制对象仍是代码段

synchronized的两大不足

相关文章
相关标签/搜索