线程安全
线程安全,是指每次运行结果和单线程运行的结果是一样的。
synchronized
Java语言的关键字,修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
- 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
- 当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁,其他线程对object中所有其它synchronized(this)同步代码块的访问也将被阻塞。
synchronized 关键字,它包括两种用法:synchronized方法 和 synchronized块
1 通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized(syncObject) {
//允许访问控制的代码
}
线程安全,是指每次运行结果和单线程运行的结果是一样的。
synchronized
Java语言的关键字,修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
- 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
- 当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁,其他线程对object中所有其它synchronized(this)同步代码块的访问也将被阻塞。
synchronized 关键字,它包括两种用法:synchronized方法 和 synchronized块
1 通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法,控制对类成员变量的访问:每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞。
不只是类实例,每一个类也对应一把锁,这样也可将类的静态成员函数声明为synchronized ,以控制其对类的静态成员变量的访问。synchronized方法的缺陷:若将一个大的方法声明为synchronized 将会影响效率。解决办法就是 synchronized块。
2 synchronized块:
通过synchronized关键字来声明synchronized块。语法如下:synchronized(syncObject) {
//允许访问控制的代码
}
synchronized块是这样一个代码块,其中的代码必须获得对象 syncObject(如前所述,可以是类实例或类)的锁方能执行。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
以下是线程安全的Singleton模式的实现:
public class Singleton {
public static Singleton getInstance() {
// Note, we don't want a synchronized method getInstance() because of efficiency
if (s == null) {
synchronized(Singleton.class){
// This check is for avoiding another thread to new again
if (s == null){
s = new Singleton();
}
}
}
return s;
}
public int getValue() {
return value;
}
public void setValue(int v) {
value = v;
}
private Singleton(){
value = 0;
}
private static Singleton s;
private int value;
}
import java.util.List;
import java.util.ArrayList;
public class TestSingleton {
public static void main(String[] args) {
final int size = 10;
List<Thread> array = new ArrayList<Thread>(size);
for (int i=0; i<size; i++) {
array.add(new Thread(new Runnable() {
public void run() {
Singleton myInstance = Singleton.getInstance();
synchronized(Singleton.class) {
myInstance.setValue(myInstance.getValue() + 1);
System.out.println("value = " + myInstance.getValue());
}
}
}));
}
for (int i=0; i<array.size(); i++) {
array.get(i).start();
}
}
}