多线程05:《疯狂Java讲义》学习笔记——线程同步

来源:互联网 发布:天然海绵知乎 编辑:程序博客网 时间:2024/05/15 21:47

注:此文为学习《疯狂Java讲义》的笔记,因此内容全部来自于该书中。

1.同步代码块

        使用同步监视器,同步代码块的语法格式为:

             synchronized(obj)

             {

       …  

                 //同步代码块

             }

       obj为同步监视器。线程开始执行同步代码块之前,必须先获得对同步监视器的锁定。通常推荐把可能被并发访问的共享资源当成同步监视器。

       “加锁->修改->释放锁”。任何线程在修改指定资源之前,首先对该资源加锁,在加锁期间其他线程无法修改该资源,当该线程修改完成后,该线程释放对该资源的锁定。通过这种方式就可以保证并发线程在任一时刻只有一个线程可以进入修改共享资源的代码区(临界区),所以同一时刻最多只有一个线程处于临界区,保证线程安全。


2.同步方法

        使用synchronized关键字来修饰某个方法,该方法称为同步方法。对于synchronized修饰的实例方法,无须指定同步监视器,同步方法的同步监视器是this,也就是调用该方法的对象。

       通过使用同步方法可以实现线程安全的类。线程安全类的特征:(1)该类的对象可以被多个线程安全地访问,(2)每个线程调用该对象的任意方法之后都将得到正确结果,(3)每个线程调用该对象的任意方法后,该对象状态依然保持合理状态。

        不可变类总是线程安全的,可变类需要其他方法来保证线程安全。

        使用线程安全的策略。(1)不要对线程安全类的所有方法都进行同步,只对那些会改变竞争资源的方法进行同步。(2)如果可变类有两种运行环境,单线程环境和多线程环境,可以为改变类提供两种版本。在单线程环境使用线程不安全版本保证性能,在多线程环境中使用线程安全版本。


3.释放同步监视器的锁定

        释放同步监视器锁定的情况。(1)当前线程的同步方法、同步代码块执行结束,当前线程即释放同步监视器。(2)当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、该方法的继续执行,当前线程会释放同步监视器。(3)当前线程在同步代码快、同步方法中出现了未处理的Error或Exception,导致了该代码块、该方法异常结束时,当前线程将会释放同步监视器。(4)当前线程执行同步代码块或同步方法时,程序执行了同步监视器对象的wait()方法,则当前线程暂停,并释放同步监视器。

        线程不会释放监视器的情况。(1)线程执行同步代码块时,程序调用Thread.sleep()、Thread.yield()方法来暂停当前线程的执行,当前线程不会释放同步监视器。(2) 线程执行同步代码块时,程序调用的suspend()方法将该线程挂起,该线程不会释放同步监视器。


4.同步锁(Lock)

        Lock是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。

        某些锁允许对共享资源并发访问,如ReadWriteLock(读写锁)。

       Java 8新增StampedLock类,为读写操作提供三种模式,Writing、ReadingOptimistic、Reading。

        线程安全中,常用的锁是ReentrantLock(可重入锁)。

class X{

      private final ReentrantLock lock=newReentrantLock();

      public void m()

     {

                 lock.lock();

      try{

                          //…method body

                 }

                 finally{

                         lock.unlock();

                 }

           }

}

        ReentrantLock锁具有可重入性。一个线程可以对已被加锁的ReentrantLock锁再次加锁。ReentrantLock对象维持一个计数器追踪lock()方法的嵌套调用。

线程在每次调用lock()方法加锁后,必须显式调用unlock()释放锁。


5.死锁

        当两个线程相互等待对方释放同步监视器时会发生死锁。JVM没有监测,也没有措施处理死锁。一旦出现死锁,程序既不会发生异常,也不会给出提示,所有线程处于阻塞状态,无法继续。


0 0
原创粉丝点击