线程再学习

package practicaljava.multithread.Praxis50; class RealTimeClock { private int clkID; private long clockTime; public int clockID() { return clkID; } public void setClockID(int id) { clkID = id; } public long time() { return clockTime; } public void setTime(long t) { clockTime = t; } // ... }

变量clkID和clockTime存储于主内存(main memory)内。但Java语言允许线程保存这些变量的私有专用副本(private working copy),这样可以便我们的两个线程更高效地运行。当线程读写这些变量时,它们操作的是private working copy,而非main memory中的正本。private working copy只在特定的同步点(synchronization point)才与main memory的正本进行一致化动作

 

 

对于synchronized锁包围的“代码所访问到的field”在进入,或者离开这块区域时,会强制private working copy—main memory一致化数据。

 

volatile类型的field,代码可以并发执行,并且保证private working copy和main memory是一致的。这种一致化动作是在每次访问这个变量的时候发生

 

记住,一旦变量被声明为volatile,在每次访问它们时,它们就与主内存进行一致化。但如果使用synchronized,只有在取得lock和释放lock时,才会对变量和主内存进行一致化

 

 

package concurrency; //: concurrency/SerialNumberGenerator.java public class SerialNumberGenerator { private static volatile int serialNumber = 0; public static int nextSerialNumber() { return serialNumber++; // Not thread-safe } } ///:~

 

下面是的SerialNumberGenerator.nextSerialNumber()函数的字节码

public static int nextSerialNumber(); Code: Stack=3, Locals=0, Args_size=0 0: getstatic #10; //Field serialNumber:I 3: dup 4: iconst_1 5: iadd 6: putstatic #10; //Field serialNumber:I 9: ireturn LineNumberTable: line 8: 0

Java递增操作不是atomic的,其涉及到一个读操作(getstatic)和一个写操作(putstatic),所以,即便是在这么简单的操作中,也为多线程问题留下来了空间。正如你所看到的,volatile在这里实际上不是什么问题,正在的问题在于nextSerialNumber()在没有synchronized的情况下对共享可变值进行了访问

 

如果将一个field定义为volatile,那么它就会告诉编译器不要执行任何移除读取和写入操作的优化,这么操作的目的是用线程的private working copy来维护对main memory的精确同步(1、practical java说“会在访问这个变量时来进行private working copy和main memory的一致化动作” 2、TIJ说“实际上,读取和写入操作都是直接针对内存的”)。

 

但是volatile并不能对递增不是atomic操作这一事实产生影响

 

synchronized有两个作用

1、为了互斥

2、为了通信(其实就是使得private working copy和main memory进行一致化动作)

而为了互斥的例子,我们见过很多,下面我们看个为了通信的例子

这里,每一个被同步的方法中的动作都是atomic的,使用同步的唯一目的是:为了通信而不是为了互斥访问

package effectivejava.multithread.item48; /** * 这里,每一个被同步的方法中的动作都是atomic的,使用同步的唯一目的是: * <p> * <b>为了通信而不是为了互斥访问</b> * * */ public class StoppableThread extends Thread { private boolean stopRequested = false; public void run() { boolean done = false; while (!stopRequested && !done) { // do what needs to be done } } public synchronized void requestStop() { stopRequested = true; } public synchronized boolean stopRequested() { return stopRequested; } }

 

你可能感兴趣的:(线程再学习)