synchronized 关键字
参考 http://blog.csdn.net/javazejian/article/details/72828483
- 修饰实例方法
作用于当前实例()加锁,进入同步代码前要获得当前实例的锁- 开启两个线程操作同一个共享资源即变量i,由于i++; 操作并不具备原子性,该操作是先读取值,然后写回一个新值,相当于原来的值加上1,分两步完成
public class AccountingSync implements Runnable{
//共享资源(临界资源)
static int i=0;
/**
* synchronized 修饰实例方法
*/
public synchronized void increase(){
i++;
}
@Override
public void run() {
for(int j=0;j<1000000;j++){
increase();
}
}
public static void main(String[] args) throws InterruptedException {
AccountingSync instance=new AccountingSync();
Thread t1=new Thread(instance);
Thread t2=new Thread(instance);
// ↑ 此时是同一个对象instance的对象锁
/** ↓ 错误,因为两个对象,实例对象锁是不同的
* Thread t1=new Thread( new AccountingSync() );
* Thread t2=new Thread( new AccountingSync() );
* 结果不可控,对 i 的访问不是互斥的
*/
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
/**
* 输出结果:
* 2000000
*/
- 开启两个线程操作同一个共享资源即变量i,由于i++; 操作并不具备原子性,该操作是先读取值,然后写回一个新值,相当于原来的值加上1,分两步完成
- 修饰静态方法
作用于当前类class对象加锁,进入同步代码前要获得当前类对象的锁- 静态成员不专属于任何一个实例对象,是类成员,因此通过class对象锁可以控制静态成员的并发操作,也就可以在 ↑ 注释中的多次实例化情况下实现互斥
- 修饰代码块
指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁- 在某些情况下,我们编写的方法体可能比较大,同时存在一些比较耗时的操作,而需要同步的代码又只有一小部分
//this,当前实例对象锁
synchronized(this){
for(int j=0;j<1000000;j++){
i++;
}
}
//class对象锁
synchronized(AccountingSync.class){
for(int j=0;j<1000000;j++){
i++;
}
}
- 在某些情况下,我们编写的方法体可能比较大,同时存在一些比较耗时的操作,而需要同步的代码又只有一小部分