synchronized官方定义:
同步方法支持一种简单的策略防止线程干扰和内存一致性错误,如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的(这一个synchronized关键字完成的)。
通俗的来讲:
synchronized关键字:能够保证同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。
synchronized的两个用法:
1.对象锁:包括方法锁(默认锁对象是当前实例对象)和同步代码块锁(自己指定锁的对象);
2.类锁:synchronized修饰的静态的方法或指定锁为Class对象;
代码展示:
对象锁:针对的是同一个对象(即下列中的instance对象),如果是两个不同的对象,对象锁就不能起到同步的作用(可以自己创两个对象测试),而类锁可以。
* 对象锁的代码块形式 * @author Administrator * */ public class SynchronizeTest01 implements Runnable{ static SynchronizeTest01 instance = new SynchronizeTest01();
Object obj = new Object(); @Override public void run() {
//锁自定义对象
synchronized (obj) {
System.out.println("我是对象锁代码块,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"玩完了");
}
//第一种锁当前对象 /*synchronized (this) { System.out.println("我是对象锁代码块,我叫"+Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"玩完了"); }*/ } public static void main(String[] args) { Thread t1 = new Thread(instance,"线程一"); Thread t2 = new Thread(instance,"线程二"); t1.start(); t2.start(); while(t1.isAlive()||t2.isAlive()) { } System.out.println("执行结束"); } }
/** * 普通方法锁形式 * @author Administrator * */ public class SynchronizeTest02 implements Runnable{ static SynchronizeTest02 instance = new SynchronizeTest02(); @Override public void run() { //调用加synchronized关键字的普通方法 method(); } public synchronized void method() { System.out.println("我是普通方法锁,我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "玩完了"); } public static void main(String[] args) { Thread t1 = new Thread(instance,"线程一"); Thread t2 = new Thread(instance,"线程二"); t1.start(); t2.start(); while(t1.isAlive()||t2.isAlive()) { } System.out.println("执行结束"); } }
普通方法锁形式
类锁:每个类可能会有多个对象,但是每个类只有一个Class对象,所以类锁的本质就是对Class对象的锁,类锁在同一时刻只能被一个对象拥有(对象锁不可以)
类锁的第一种形式:在静态方法上加锁,并创建了两个对象,依然可以解决并发问题。
/** * * 类锁的第一种形式:静态方法锁形式 * @author Administrator * */ public class SynchronizeTest02 implements Runnable{ static SynchronizeTest02 instance1 = new SynchronizeTest02(); static SynchronizeTest02 instance2 = new SynchronizeTest02(); @Override public void run() { //调用加synchronized关键字的静态方法 method(); } public static synchronized void method() { System.out.println("我是静态方法锁,我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "玩完了"); } public static void main(String[] args) { Thread t1 = new Thread(instance1,"线程一"); Thread t2 = new Thread(instance2,"线程二"); t1.start(); t2.start(); while(t1.isAlive()||t2.isAlive()) { } System.out.println("执行结束"); } }
类锁的第二种形式:
/** * * 类锁的第二种形式:代码块锁.Class形式 * @author Administrator * */ public class SynchronizeTest03 implements Runnable{ static SynchronizeTest03 instance1 = new SynchronizeTest03(); static SynchronizeTest03 instance2 = new SynchronizeTest03(); @Override public void run() { //调用加synchronized关键字的普通方法 method(); } public void method() { synchronized (SynchronizeTest03.class) { System.out.println("我是静态方法锁,我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "玩完了"); } } public static void main(String[] args) { Thread t1 = new Thread(instance1,"线程一"); Thread t2 = new Thread(instance1,"线程二"); t1.start(); t2.start(); while(t1.isAlive()||t2.isAlive()) { } System.out.println("执行结束"); } }