技术开发 频道

java线程学习总结

  1.6锁对象(实例方法的锁)

  在同步代码块中使用锁的时候,担当锁的对象可以是这个代码所在对象本身或者一个单独的对象担任,但是一定要确保锁对象不能为空。如果对一个null对象加锁,会产生异常的。原则上不要选择一个可能在锁的作用域中会改变值的实例变量作为锁对象。

  锁对象,一种是对象自己担任,一种是定义一个普通的对象作为private property来担任,另外一种是建立一个新的类,然后用该类的实例来担任。

  参考 :

  thread.lock.UseSelfAsLock,使用对象自己做锁对象

  thread.lock.UseObjAsLock 使用一个实例对象作锁对象

  thread.lock.UseAFinalObjAsLock使用常量对象作为一个锁对象

  1.7类锁

  实例方法存在同步的问题,同样,类方法也存在需要同步的情形。一般类方法的类锁是一个static object来担任的。当然也可以采用类本身的类对象来作为类锁。

  一个类的实例方法可以获得该类实例锁,还可以尝试去访问类方法,包含类同步方法,去获得类锁。

  一个类的类方法,可以尝试获得类锁,但是不可以尝试直接获得实例锁。需要先生成一个实例,然后在申请获得这个实例的实例锁。

  参考

  thread.lock.UseStaticObjAsStaticLock 使用类的属性对象作为类锁。

  thread.lock.UseClassAsStaticLock使用类的类对象作为类锁

  1.8.线程安全方法与线程不安全方法

  如果一个对象的所有的public方法都是同步方法,也就是说是public方法是线程安全的,那该对象的private方法,在不考虑继承的情况下,可以设置为不是线程安全的方法。

  参考 thread.lock.SynMethrodAndNotSynMethrod

  1.9类锁和实例锁混合使用

  在实例方法中混合使用类锁和实例锁;可以根据前面说的那样使用实例锁和类锁。

  在类方法中混合使用类锁和实例锁,可以根据前面说的那样使用类锁,为了使用实例锁,先得生成一个实例,然后实例锁。

  参考 thread.lock.StaticLockAndObjLock

  1.10锁的粒度问题。

  为了解决对象锁的粒度过粗,会导死锁出现的可能性加大,锁的粒度过细,会程序开发维护的工作加大。对于锁的粒度大小,这完全要根据实际开发需要来考虑,很难有一个统一的标准。

  1.11.读写锁

  一个读写锁支持多个线程同时访问一个对象,但是在同一时刻只有一个线程可以修改此对象,并且在访问进行时不能修改。

  有2种调度策略,一种是读锁优先,另外就是写锁优先。

  参考 thread.lock.ReadWriteLock

  1.12 volatile

  在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步。这在JVM 1.2之前,Java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。

0
相关文章