java同步机制及synchronized关键字的应用

Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如何?还得对synchronized关键字的作用进行深入了解才可定论。

总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。

在进一步阐述之前,我们需要明确几点:

A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

B.每个对象只有一个锁(lock)与之相关联。

C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。


接着来讨论synchronized用到不同地方对代码产生的影响:
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。

1. 把synchronized当作函数修饰符时,示例代码如下:

Java代码 复制代码
  1. Public synchronized void methodAAA() {
  2. //....
  3. }
Public synchronized void methodAAA() { 
  //....
} 


这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。

上边的示例代码等同于如下代码:

Java代码 复制代码
  1. public void methodAAA() {
  2. synchronized (this) // (1)
  3. { //….. }
  4. }
public void methodAAA() { 
  synchronized (this) //  (1) 
  { //….. } 
} 


(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。

可见同步方法实质是将synchronized作用于object reference。 那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱。


2.同步块,示例代码如下:

Java代码 复制代码
  1. public void method3(SomeObject so) {
  2. synchronized(so) {
  3. //…..
  4. }
  5. }
public void method3(SomeObject so) { 
  synchronized(so) { 
       //….. 
  } 
} 


这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

Java代码 复制代码
  1. class Foo implements Runnable {
  2. private byte[] lock = new byte[0]; // 特殊的instance变量
  3. Public void methodA() {
  4. synchronized(lock) { //… }
  5. }
  6. //…..
  7. }
class Foo implements Runnable { 
      private byte[] lock = new byte[0];  // 特殊的instance变量 

    Public void methodA() { 
       synchronized(lock) { //… } 
      } 

      //….. 
} 


注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。


3.将synchronized作用于static 函数,示例代码如下:

Java代码 复制代码
  1. Class Foo {
  2. public synchronized static void methodAAA() // 同步的static 函数
  3. { .... }
  4. public void methodBBB() {
  5. synchronized(Foo.class) // class literal(类名称字面常量)
  6. }
  7. }
 Class Foo {

  public synchronized static void methodAAA()   // 同步的static 函数 
 { .... } 

  public void methodBBB() {
       synchronized(Foo.class)   //  class literal(类名称字面常量) 
  } 

} 



代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。

记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。

可以推断:

如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。


小结如下:
搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。 还有一些技巧可以让我们对共享资源的同步访问更加安全:

1. 定义private 的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。

2. 如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=677720

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23170052/viewspace-1030492/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/23170052/viewspace-1030492/

!qhyb.rar 当 CAD 缺失对应字体时,图纸文字会显示异常,出现乱码、问号。将下载好的字体文件复制到 AutoCAD 的 Fonts 文件夹中,即可恢复正常显示。 立即下载

相关推荐

政府科技管理部门如何实现科技成果高效转化?.docx

政府科技管理部门如何实现科技成果高效转化?

Javasynchronized同步锁用法及作用范围

Java 中的 synchronized 关键字可以在多线程环境下用来作为线程安全的同步锁。本文主要对 synchronized 的作用,以及其有效范围进行讨论。 Java中的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的

在梅边的专栏 7万+

librdkafka Windows 包(可直接使用)

librdkafka/win ├─ bin/ # 全部运行时dll + pdb调试符号 + plugins插件目录 ├─ include/ # 头文件 rdkafka.h └─ lib/ # .lib静态导入库(链接阶段使用)

java同步机制synchronized关键字应用1

Java对多线程的支持与同步机制深受大家的喜爱,通过JMM可以了解到几个涉及多线程编程的几个关键字synchronized、final、volatile。   一、作用 1.synchronized 1.1 synchronized优点: 正确使用synchronized可以解决data race问题,同时保证了变量的可见性; 1.2 synchronized缺点: syn...

廉颇老矣,尚能饭否? (jdk+算法+spring+netty+大数据+OS+Architect) 248

Java线程同步:synchronized锁住的是代码还是对象

Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。Synchronized既可以对代码块使用,也可以加在整个方法上。   关键是,不要认为给方法或者代码段加上synchronized就万事大吉,看下面一段代码: class Sync { public synchronized void test

叉叉哥的BLOG 11万+

Java面试题:Java内存模型、同步与线程池的综合应用synchronized关键字同步机制,线程池的原理与性能提升,并发编程的最佳实践

问题具体原理:原子性指的是一个操作在其他线程看来是不可分割的,即在多个线程环境中,一个操作要么完全执行,要么完全不执行;线程池是一种线程管理模式,它可以复用线程,减少线程创建和销毁的开销,提高程序的性能。线程池中的线程会循环使用,任务到达时,线程池会从任务队列中取出任务并分配给空闲的线程执行。面试题3:请解释Java中的线程池(ThreadPool)的工作原理,并解释为什么使用线程池能够提高程序的性能。在Java虚拟机层面,考察重点:对线程池的理解,包括它的工作原理以及在使用线程池时能够带来的性能优势。

码农超哥的博客 584

java同步机制synchronized关键字应用2

类定义:   public class Test{ public synchronized method1(){...} public synchronized method2(){...} }   问题:   多线程并发访问method1和method2时,两者会互斥吗?   下面的测试程序来回答这个问题。 public class TestSynchroni...

廉颇老矣,尚能饭否? (jdk+算法+spring+netty+大数据+OS+Architect) 166

Java同步机制总结--synchronized

Java同步机制总结--synchronized 不久前用到了同步,现在回过头来对JAVA中的同步做个总结,以对前段时间工作的总结和自我技术的条理话。JAVAsynchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。假如再细的分类,synchronized可作用于instance变量、object reference(对象引用)、st

xiaofengxiaoling的专栏 445

关于Java同步机制synchronized同步方法

Java同步机制中被synchronized关键字修饰的有两种,一种是同步块,另一种是同步方法。现在直说同步方法 在同步方法中,被synchronized关键字修饰的方法的作用域有两种: a. 作用域是某个实例内,synchronized Method(){ }可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象中有多个synchroniz...

weixin_34247155的博客 1013

Java关键字synchronized

synchronized 每一个用synchronized关键字声明的方法都是临界区。在Java中,同一个对象的临界区,在同一时间只有一个允许被访问。当一个线程试图访问一个临界区时,它将使用一种同步机制来查看是不是已有其他线程进入临界区。如果没有其他线程进入临界区,它就可以进入临界区;如果已有线程进入了临界区,它就被同步机制挂起,直到进入的线程离开这个临界区。如果在等待进入临界区的线程不止一个,...

lazyRabbit的博客 285

Synchronized关键字

文章目录Synchronized关键字说明实例方法静态方法实例方法中的代码块静态方法中的代码块Synchronized用例 Synchronized关键字说明   Java中的同步代码块用Synchronized关键字来标记。在Java中的一个同步代码块有时是同步在不同的对象上的。在相同的对象上,在同一时间内所有的同步代码块中只有一个线程在执行。所有其它的线程都在试图进入同步代码块时被阻塞,直到同...

ZZY1078689276的专栏 329

文章六:Java中的同步机制

同步机制在多线程环境中起着至关重要的作用,能够防止数据竞态条件,保证数据的一致性和正确性。每个对象都有一个监视器,当线程进入同步代码块或方法时,会尝试获取对象的监视器锁。在实际开发中,根据具体需求选择合适的同步机制,可以大大提升并发编程的效率和可靠性。提供了一种分离读写锁的机制,允许多个读线程同时访问共享资源,但在写线程访问共享资源时,所有的读线程和其他写线程都将被阻塞。关键字Java 提供的最基础的同步机制,用于确保同一时间只有一个线程可以访问同步代码块或方法。包中的一个显式锁类,它提供了比。

深度学习客 1226

java的线程同步机制synchronized关键字的理解

转自:http://arthennala.blog.51cto.com/287631/56356/ 线程同步:                由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。 需要明确的几个问题:        1)synchr

lianghongge的专栏 811

国有企业如何推动科技创新与产业升级融合?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务如何实现数字化升级?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

兄弟MFC-J2330DW 中文维修手册

兄弟MFC-J2330DW 中文维修手册

CesiumForUnitySamples-v1.25.1

Cesium for Unity 是一个官方插件,它将 Cesium 强大的3D 地理空间平台能力深度集成到了 Unity 引擎中。简单来说,它让你能在 Unity 里创建出一个高精度的真实地球,并加载和探索全球范围内的海量地理数据

政府科技管理部门如何降低平台建设成本?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

cuihu9495
博客等级 码龄10年 0粉丝 0原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值