synchronized是Java中的关键字,是一种同步锁 它能够用来修饰方法和代码块多线程
多线程的状况下 synchronized 修饰的方法和代码块会让一个线程执行(锁住代码),另外的线程等待ide
下面咱们经过一个例子来看下spa
public class Synchronized { public void test(String tag) { if ("a".equals(tag)) { System.out.println("a"); } else if ("b".equals(tag)) { System.out.println("b"); } System.out.println("当前线程:"+Thread.currentThread().getName()); System.out.println("the end"); } public static void main(String[] args) { // TODO Auto-generated method stub final Synchronized s1 = new Synchronized(); final Synchronized s2 = new Synchronized(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s1.test("a"); } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s2.test("b"); } },"t2"); t1.start(); t2.start(); } }
启动两个线程 调用方法 test 运行结果是这样的 这是没加synchronized 关键字的状况,线程
(屡次运行结果可能不一样)code
a 当前线程:t1 b 当前线程:t2 the end the end
这个结果表示一个线程不会等到另外一个线程执行完再执行对象
若是是一个线程等待另外一个线程执行完的话 打印结果应该是get
a
当前线程:t1
the end
b
当前线程:t2
the end同步
或者 class
b
当前线程:t2
the endtest
a
当前线程:t1
the end
下面 咱们在 test方法上加 synchronized 关键字看下打印结果
public class Synchronized { // 加 synchronized 修饰 public synchronized void test(String tag) { if ("a".equals(tag)) { System.out.println("a"); } else if ("b".equals(tag)) { System.out.println("b"); } System.out.println("当前线程:"+Thread.currentThread().getName()); System.out.println("the end"); } public static void main(String[] args) { // TODO Auto-generated method stub final Synchronized s1 = new Synchronized(); final Synchronized s2 = new Synchronized(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s1.test("a"); } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s2.test("b"); } },"t2"); t1.start(); t2.start(); } }
运行结果
a b 当前线程:t1 the end 当前线程:t2 the end
发如今方法上加上 synchronized关键字后 仍是没有实现一个线程执行时(锁住代码),另外的线程等待执行完后再执行的效果。
咱们来看下代码
t1线程启动 调用s1.test();方法
这个方法在执行的时候 是看到了test synchronized 关键字的 因此方法执行的时候线程会先去尝试得到对象锁,这时候 的锁就是对象s1的锁,
t2线程启动 调用s2.test()方法
一样t2线程在执行到test方法时也看到了 synchronized 关键字 因此这时候线程也会去尝试得到对象锁 ,
若是这时候,对象锁被其余线程得到了 那么t2线程就进入阻塞 等待状态 ,
咱们开始会认为 t2线程走到s2.test()的时候 t1线程已经得到了锁,因此t2线程这会会阻塞,
但实际上t1线程得到的是 s1的锁,t2执行到 test方法时 要判断锁是否被其余线程得到,这个锁是s2的对象锁,两个线程得到的锁是不一样对象的 因此相互间不影响 ,因此这两个线程不会等到另一个线程执行完再执行
咱们换一种写法让 不一样的线程调用到test方法时要获取的对象锁是同样的
public class Synchronized { public void test(String tag) { if ("a".equals(tag)) { System.out.println("a"); } else if ("b".equals(tag)) { System.out.println("b"); } System.out.println("当前线程:"+Thread.currentThread().getName()); System.out.println("the end"); } public static void main(String[] args) { // TODO Auto-generated method stub final Synchronized s1 = new Synchronized(); final Synchronized s2 = new Synchronized(); //这里lock 只是对象的名字 由于功能上比较像锁 因此就取这名 跟jdk里面的Lock不要紧 // 后面线程执行的时候都会先获取到这个对象的锁 一个线程只有在方法执行完后 才会把这个对象的锁释放掉 final Object lock = new Object(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { synchronized (lock) { // TODO Auto-generated method stub s1.test("a"); } } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { synchronized (lock) { // TODO Auto-generated method stub s2.test("b"); } } },"t2"); t1.start(); t2.start(); } }
这时候的运行结果就知足咱们的预期了。
synchronized 修饰 static 方法
方法加上static 后就是类的方法了 不属于任何对象 这时候在方法上在加上synchronized 修饰 做用的对象是这个类的全部对象,
像前面说的 test 方法 加了 synchronized 修饰后 再加 static 修饰 也能实现 一个线程等待另一个线程执行完的效果