线程的系统都写完了,遇到很多问题,刚开始写到处都在synchronized,跌倒又爬起来,现在回过头来看看JAVA并发实践,开始整理下。
《JAVA并发编程实践》说线程安全就是,在单线程执行时候,实例状态是正确的,在多线程执行的时候,状态仍要正确:
a class is thread-safe when it continues to behave correctly when accessed
from multiple threads.
下面这段代码,如果在单线程下,Counter的状态(由count来表示其状态)应该是从1、2、3.。。。20.
并发后状态就坏掉了,这就是按他定义的线程不安全:
如在run方法中调用Counter类的increase和increase2方法,他们是线程安全的,输出都是0、1、2、3.。。。
而increase3则是:0 1 1 2 4 5 6 7 8 9 10 11 12 13 14 15 16 16 18 19
package com.zyp.test.concurrent;
public class Counter {
private int count = 0;
public int increase(){
synchronized (this) {
System.out.print(count+" ");
return count++;
}
}
public synchronized int increase2(){
System.out.print(count+" ");
return count++;
}
public int increase3(){
System.out.print(count+" ");
return count++;
}
public int getCount() {
return count;
}
}
package com.zyp.test.concurrent.thread;
import com.zyp.test.concurrent.Counter;
public class CounterThread extends Thread{
private Counter counter;
public CounterThread(Counter counter){
this.counter = counter;
}
public void run(){
//此处测试三种increase方法
counter.increase();
// counter.increase2();
// counter.increase3();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
Counter counter = new Counter();
for(int i = 0;i<20;i++){
CounterThread t = new CounterThread(counter);
t.start();
if(i%3==0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
由于内部锁是基于线程而非调用的,当一个线程执行increase方法时,已经拿到了counter对象引用的锁,那么其他线程执行执行同一个counter对象的increase或increase2会堵塞等待counter对象锁。
按《JAVA并发编程实践》里面的建议是,如果状态变量会被一个线程修改,那么所有其他访问(access)该状态变量的线程访问时都要同步。(包括读操作)
******************
摘录一点《JAVA并发编程实践》:
Whenever more than one thread accesses a given state variable, and one of them might
write to it, they all must coordinate their access to it using synchronization.
无论何时有多个线程要访问一个状态变量(实例的成员变量),其中有一个线程可能会写状态变量的值,那么所有线程必须通过同步来协调他们对状态变量的访问。
No set of operations performed sequentially or concurrently on instances of a thread-safe class can cause an instance to be in an invalid state。
顺序执行的一组操作或在线程安全的类的多个实例上并发执行的操作,将不会造成实例的状态变量不正确。