第一章Synchronzied简介
1、作用
官方介绍
翻译:同步方法支持一种简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的
一句话说出Synchronized的作用:能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果
2、地位
- Synchronized是Java的关键字,被Java语言原生支持
- 是最基本的互斥同步手段
- 是并发编程中的元老级角色,是并发编程的必学内容
3、不使用并发手段的后果演示
代码实战:两个线程同时a++,最后结果会比预计的少
public class DisappearRequest1 implements Runnable { static DisappearRequest1 instance = new DisappearRequest1(); static int i=0; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(instance); Thread t2 = new Thread(instance); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); //运行结果总是小于200000 } @Override public void run() { for (int j=0; j<100000; j++){ i++; } } }
原因:count++,它看上去只是一个操作,实际上包含了三个动作:
1、读取count
2、将count加一
3、将count的值写入到内存中
第二章Synchronized的两种用法
1、对象锁
包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(this或自己指定锁对象)
1⃣️代码块形式:
this
public class SynchronizedObjectCodeBlock2 implements Runnable { static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2(); @Override public void run() { 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("finished"); } }
手动指定锁对象
不同锁对象
public class SynchronizedObjectCodeBlock2 implements Runnable { static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2(); Object lock1 = new Object(); Object lock2 = new Object(); @Override public void run() { synchronized (lock1){ System.out.println("我是lock1。我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "lock1部分运行结束。"); } synchronized (lock2){ System.out.println("我是lock2。我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "lock2部分运行结束。"); } } 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("finished"); } }
相同锁对象
public class SynchronizedObjectCodeBlock2 implements Runnable { static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2(); Object lock1 = new Object(); Object lock2 = new Object(); @Override public void run() { synchronized (lock1){ System.out.println("我是lock1。我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "lock1部分运行结束。"); } synchronized (lock1){ System.out.println("我是lock2。我叫" + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "lock2部分运行结束。"); } } 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("finished"); } }
2⃣️方法锁形式:synchronized修饰普通方法,锁对象默认为this
public class SynchronizedObjectMethod3 implements Runnable { static SynchronizedObjectMethod3 instance = new SynchronizedObjectMethod3(); 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("finished"); } @Override public void run() { 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() + "运行结束"); } }
2、类锁
指synchronized修饰静态的方法或指定锁为Class对象