关键字synchronized的作用是实现线程间的同步。
它的工作是对同步的代码加锁,使得每一次,只能有一个线程进入同步块,从而保证线程间的安全性。
synchronized 与 volatile
synchronized除了用于线程同步、确保线程安全外,还可以保证线程间的可见性和有序性。
可见性上:synchronized完全可以替代volatile的功能,只是使用上没那么方便;
有序性上:由于synchronized限制每次仅有一个线程可以访问同步块,换言之,被synchronized限制的多个线程时串行执行的),这样有序性的问题自然得到了解决。
用法
Java中的每一个对象都可以作为锁,具体表现为3中形式
- 普通同步方法,锁是当前实例对象
- 静态同步方法,锁是当前类的Class对象
- 同步方法块,锁是synchronized括号里配置的对象
普通同步方法与静态同步方法的区别
/**
* 普通同步方法 与 静态同步方法的区别
*/
public class Async {
public static int i =0 ;
public static class AsyncRunnable implements Runnable{
// 尝试 不加static和加static的区别
public synchronized static void add(){
i++;
}
@Override
public void run() {
for(int j=0; j<10000; j++){
add();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new AsyncRunnable() );
t1.start();
Thread t2 = new Thread(new AsyncRunnable() );
t2.start();
t1.join();
t2.join();
System.out.println( i );
}
}
程序说明:
如果add()方法不加static方法修饰,那么锁的是当前的实例,t1和t2线程分别各自实例化了一个对象,使用了两把不同的锁,所以程序中的i的数据安全是无法保证的,程序输出的结果会小于20000的值。