Synchronized一些想法
1. Java中对象对wait(),和notify()方法的调用前提是:
当前线程必须获得该对象的锁(Monitor),否则会抛出IllegalMonitorStateException,且这两个方法必须在同步代码块中调用。wait():让访问当前对象的线程阻塞。
2.Synchronized关键字:
修饰实例方法:实际保护的是同一个对象(即当前对象this)方法的调用,确保同时只能有一个线程执行。即保护的是对象而不是方法,只要访问同一个对象的Synchronized方法,都会被顺序执行。但是Synchronized不能防止非Synchronized方法被同时执行。
修饰静态方法:实际保护的是类对象(class对象),不同的两个线程可以一个执行synchronized实例方法,另一个执行synchronized的静态方法。
代码块:可以所任何对象,即就是任何对象都可以作为锁。
3.进一步理解Synchronized关键字:
3.1 可重入性:对于一个执行线程,当它获得锁之后,再调用其他需要同样锁的代码时,可以直接调用,意义在于防止死锁,也称为递归锁。如下代码执行结果:每个线程名都会被连续打印两次。
1 1 public class SynchronizedLock { 2 2 public static void main(String[] args) { 3 3 Test1 t1=new Test1(); 4 4 new Thread(t1,"1_Thread").start(); 5 5 new Thread(t1,"2_Thread").start(); 6 6 new Thread(t1,"3_Thread").start(); 7 7 8 8 } 9 9 } 10 10 class Test1 implements Runnable{ 11 11 @Override 12 12 public void run() { 13 13 Method1(); 14 14 15 15 } 16 16 public synchronized void Method1(){ 17 17 System.out.println(Thread.currentThread().getName()); 18 18 Method2(); 19 19 } 20 20 21 21 private synchronized void Method2() { 22 22 System.out.println(Thread.currentThread().getName()); 23 23 24 24 } 25 25 }
3.2内存可见性:Synchronized保证了内存可见性,具体为:在获得锁后会从内存中获取最新的数据,在释放锁时,会将数据写回内存中。但是如果只是为了保证内存的可见性,则Synchronized的成本有点高,可以选择Volatile,是一个轻量级的锁,来保证内存的可见性问题。
public class TestVolatile { public static void main(String[] args) throws InterruptedException { new Thread(new TestV()).start(); //启动线程 Thread.sleep(2000); //主线程休眠 TestV.setA(); //设置Flag } } class TestV implements Runnable{ volatile static boolean flag=true; int a=1; @Override public void run() { while(flag==true){ System.out.println(a++); } } public static void setA(){ if(flag==true){ flag=false; System.out.println("flag 已经被修改"); } } }