zoukankan      html  css  js  c++  java
  • 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");
        }
    }

    #

    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  

    现象

    在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();
            }
        }

    执行结果

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

    现象

    可以看到当他们共用一个对象的时候,synchonized起了作用,这块代码是串行执行的

    结论

    锁住的是对象

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

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

    这样是没问题,但是,比较多的做法是让synchronized锁这个类对应的Class对象。

    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的两大不足

  • 相关阅读:
    vue学习笔记之v-if
    vue学习笔记之属性和方法
    vue学习笔记之v-for与-repeat
    王阳明心学
    读《铁血并购》
    心理测试:DISC性格测试(完整版)
    关于旅行
    [转载]win32 计时器使用
    [转]C#中调用资源管理器(Explorer.exe)打开指定文件夹 + 并选中指定文件 + 调用(系统默认的播放类)软件(如WMP)打开(播放歌曲等)文件
    [转]C#读写TEXT文件
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/10079916.html
Copyright © 2011-2022 走看看