1、从零开始学Java 有关线程的学习总结从零开始学Java 有关线程的学习总结1 .资源冲突,如果两个线程确实是在修改同一个对象,共享资源的冲突将变得更糟糕,因为这有可能把对象设置成不正确的状态。通过简单的“信号量”概念引入, 把它看作是在两个线程之间进行通信的标志对象。如果信号量的值是零,则它监控的资源是可用的,但如果这个值是非零的,则被监控的资源不可用,所以线程必须 等待。当资源可用的时候,线程增加信号量的值,然后继续执行这个被监控的资源。把增加和减少信号量的操作定义为原子操作,这样就可保证两个线程同时访问同 一资源的时候不至于冲突。定义一个简化的信号量:1. 2. 3. publiccla
2、ssSemaphoreimplementsInvariant20. privatevolatileintsemaphore=0;28. publicbooleanavailable()returnsemaphore=0;37. publicvoidacquire()+semaphore;42. publicvoidrelease()-semaphore;47. publicInvariantSateinvariant()51. intval=semaphore;53. if(val=0|val=1)59. returnnewInvariantOk();63. else65. returnnew
3、InvariantFailure(newInteger(val);71. 72. 12345678910111213(其中Invariant接口在博客:线程测试框架已给出)将semaphore字段设置为volatile ,以确保编译器不会对任何读取此值的操作进行优化。2.解决共享资源竞争,之前说过,可以通过yield()和setPriority()来给线程调度机制提供建议,但这些建议未必会有多大的效果,这取决 与你的具体平台和JVM实现。Java以提供关键字 synchronized 的形式,为防止资源冲突提供了内置支持。共享资源一般是以对象的形式存在的内存判断,但也可以是文件,输入/输出端口
4、,或者是打印机。要控制对共享资源的 访问,得先把它包装进一个对象。然后把所有要访问这个资源的方法标记为synchronized。即一旦某个线程处于一个标记为synchronized 的方法中,那么在这个线程从该方法返回之前,其他所有要调用类中任何标记为synchronized方法的线程都会被阻塞。每个对象都含有单一的锁(也称为监视器),这个锁本身就是对象的一部分(不用写任何特殊代码)。当在对象上调用其任意synchronized方法的时 候,此对象都被加锁,这时该对象上的其他synchronized方法也只能等到前一个方法调用完并释放了锁之后才能被调用。针对每一个类也有一个锁(作为类的Clas
5、s对象的一部分),所以synchronized static 方法可以在类的范围内防止对static数据的并发访问。3.原子操作,即不能被线程调度机制中断的操作;一旦操作开始,那么它一定可以在可能发生的“上下文切换”之前(切换到其他线程执行)执行完毕。如果问题 中的变量类型是除long或double以外的基本类型,对这种变量进行简单的赋值或返回值操作的时候,才算是原子操作。然而,只要给long或 double加上volatile,操作就是原子的了。注意,在JVM中的自增加操作并不是原子操作,它牵涉到一次读和一次写,所以即使在这样的简单操作 中,也为线程出问题提供了空间。线程工作时,每个线程都可
6、能拥有一个本地栈来维护一些变量的复本,如果把一个变量定义成volatile的,就等于告诉编 译器不要做任何优化,直接在主存操作变量。4.保证上述问题解决,做安全的做法就是使用下面的方法:1)如果要对类中的某个方法进行同步控制,最好同步所有方法。如果忽略了其中一个,通常很难确定这么做是否会有负面影响。2)当去除方法的同步控制时,要非常小心。通常这么做是基于性能方面的考虑,但在JDK1.3和JDK1.4中,同步控制所需的负担已经大大的减少。此外,只应在使用性能评价工具证实了同步控制确实是性能瓶颈的时候,才这么做。5.如果只是希望防止多个线程同时访问方法内部的部分代码而不是防止整个方法,可以使用sy
7、nchronized关键字来分离代码段,这种方式被称为“临界区”,此时,synchronized被用来指定某个对象,此对象的锁被用来对花括号内的代码进行同步控制:1. synchronized(syncObject)10. /Thiscodecanbeaccessed12. /byonlyonethreadatatime14. 1234使用同步控制块,而不是对整个方法进行同步控制,可以使多个线程访问对象的时间性能得到显著的提高。要注意的是,当对象中的方法在不同的锁上同步的时候,两个线程可以访问同一个对象:1. classDualSynch8. 9. privateObjectsyncObject=11. newObject();13. 14. publicsynchronizedvoidf()19. System.out.println(Insidef();23. try25. Thread.sleep(500);27. catch(InterruptedExceptione)29. spanclass=hljs-k
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1