synchronized用于多线程设计,有了synchronized关键字,多线程程序的运行结果将变得可以控制。synchronized关键字用于保护共享数据。
synchronized实现同步的机制:synchronized依靠"锁"机制进行多线程同步,"锁"有2种,一种是对象锁,一种是类锁。
1.依靠对象锁锁定
初始化一个对象时,自动有一个对象锁。synchronized {普通方法}依靠对象锁工作,多线程访问synchronized方法,一旦某个进程抢得锁之后,其他的进程只有排队对待。
synchronized {普通方法}依靠对象锁工作,多线程访问synchronized方法,一旦某个进程抢得锁之后,其他的进程只有排队对待。
synchronized void method{}功能上,等效于
void method{
synchronized(this) {
...
}
}
通过代码看比较清楚:
public class TestSynchronized { public synchronized void method1() throws InterruptedException { System.out.println("method1 begin at:" + System.currentTimeMillis()); Thread.sleep(6000); System.out.println("method1 end at:" + System.currentTimeMillis()); } public synchronized void method2() throws InterruptedException { while(true) { System.out.println("method2 running"); Thread.sleep(200); } } static TestSychronized instance = new TestSychronized(); public static void main(String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { instance.method1(); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=1; i<4; i++) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread1 still alive"); } } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { try { instance.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread1.start(); thread2.start(); } }
运行结果:thread2一直等到thread1中的method1执行完了之后才执行method2,说明method1和method2互斥
synchronized {修饰代码块}的作用不仅于此,synchronized void method{}整个函数加上synchronized块,效率并不好。在函数内部,可能我们需要同步的只是小部分共享数据,其他数据,可以自由访问,这时候我们可以用 synchronized(表达式){//语句}更加精确的控制。
- 2.synchronized {static方法}此代码块等效于
void method{
synchronized(Obl.class)
}
}
使用该类的类对象的锁定去做线程的共享互斥.
package com.free4lab.lol; public class TestSychronized { public synchronized static void method1() throws InterruptedException { System.out.println("method1 begin at:" + System.currentTimeMillis()); Thread.sleep(6000); System.out.println("method1 end at:" + System.currentTimeMillis()); } public synchronized static void method2() throws InterruptedException { while(true) { System.out.println("method2 running"); Thread.sleep(200); } } static TestSychronized instance1 = new TestSychronized(); static TestSychronized instance2 = new TestSychronized(); public static void main(String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { instance1.method1(); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=1; i<4; i++) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread1 still alive"); } } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { try { instance2.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread1.start(); thread2.start(); } }
输出效果也是method1和method2互斥
- 3.synchronized {run方法}run方法的锁定.
这个举例比较好说
package com.free4lab.lol; public class TestSychronized { static TestSychronized instance = new TestSychronized(); public static void main(String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public synchronized void run() { for(int i=1; i<4; i++) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread1 still alive, " + i); } } }); new Thread(thread1).start(); new Thread(thread1).start(); } }
如果加了synchronized当前线程取完所有数据后,才会释放锁,输出结果是有序的
Thread1 still alive, 1 Thread1 still alive, 2 Thread1 still alive, 3 Thread1 still alive, 1 Thread1 still alive, 2 Thread1 still alive, 3