zoukankan      html  css  js  c++  java
  • java多线程中synchronized关键字的用法

    转自:http://www.cdtarena.com/javapx/201308/9596.html

         由于同一进程内的多个线程共享内存空间,在Java中,就是共享实例,当多个线程试图同时修改某个实例的内容时,就会造成冲突,因此,线程必须实现共享互斥,使多线程同步。

        最简单的同步是将一个方法标记为synchronized,对同一个实例来说,任一时刻只能有一个synchronized方法在执行。当一个方法正在执行某个synchronized方法时,其他线程如果想要执行这个实例的任意一个synchronized方法,都必须等待当前执行 synchronized方法的线程退出此方法后,才能依次执行。

        但是,非synchronized方法不受影响,不管当前有没有执行synchronized方法,非synchronized方法都可以被多个线程同时执行。

        此外,必须注意,只有同一实例的synchronized方法同一时间只能被一个线程执行,不同实例的synchronized方法是可以并发的。例如,class A定义了synchronized方法sync(),则不同实例a1.sync()和a2.sync()可以同时由两个线程来执行。

        多线程同步的实现最终依赖锁机制。我们可以想象某一共享资源是一间屋子,每个人都是一个线程。当A希望进入房间时,他必须获得门锁,一旦A获得门锁,他进去后就立刻将门锁上,于是B,C,D就不得不在门外等待,直到A释放锁出来后,B,C,D中的某一人抢到了该锁(具体抢法依赖于 JVM的实现,可以先到先得,也可以随机挑选),然后进屋又将门锁上。这样,任一时刻最多有一人在屋内(使用共享资源)。

        Java语言规范内置了对多线程的支持。对于Java程序来说,每一个对象实例都有一把"锁",一旦某个线程获得了该锁,别的线程如果希望获得该锁,只能等待这个线程释放锁之后。获得锁的方法只有一个,就是synchronized关键字。例如:

        public class SharedResource {

        private int count = 0;

        public int getCount() { return count; }

        public synchronized void setCount(int count) { this.count = count; }

        }

        同步方法public synchronized void setCount(int count) { this.count = count; } 事实上相当于:

        public void setCount(int count) {

        synchronized(this) { // 在此获得this锁

        this.count = count;

        } // 在此释放this锁 http://www.cdtarena.com/ruanj.html

        }

        红色部分表示需要同步的代码段,该区域为"危险区域",如果两个以上的线程同时执行,会引发冲突,因此,要更改SharedResource的内部状态,必须先获得SharedResource实例的锁。

        退出synchronized块时,线程拥有的锁自动释放,于是,别的线程又可以获取该锁了。

        为了提高性能,不一定要锁定this,例如,SharedResource有两个独立变化的变量:成都java培训

        public class SharedResouce {

        private int a = 0;

        private int b = 0;

        public synchronized void setA(int a) { this.a = a; }

        public synchronized void setB(int b) { this.b = b; }

        }

        若同步整个方法,则setA()的时候无法setB(),setB()时无法setA()。为了提高性能,可以使用不同对象的锁:

        public class SharedResouce {

        private int a = 0;

        private int b = 0;

        private Object sync_a = new Object();

        private Object sync_b = new Object();

        public void setA(int a) {

        synchronized(sync_a) {

        this.a = a;

        }

        }

        public synchronized void setB(int b) {

        synchronized(sync_b) {

        this.b = b;

        }

        }

  • 相关阅读:
    datanode报错Problem connecting to server
    使用命令查看hdfs的状态
    Access denied for user root. Superuser privilege is requ
    ElasticSearch默认的分页参数 size
    SparkStreaming Kafka 维护offset
    【容错篇】Spark Streaming的还原药水——Checkpoint
    251 Android 线性与相对布局简介
    250 Android Studio使用指南 总结
    249 如何解决项目导入产生的中文乱码问题
    248 gradle更新问题
  • 原文地址:https://www.cnblogs.com/cdtarena/p/3259715.html
Copyright © 2011-2022 走看看