本文共 9304 字,大约阅读时间需要 31 分钟。
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
一、修饰代码块
package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on 2020/6/24 10:53 * @description 一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞。 */public class SyncThreadDemo1 implements Runnable { private static int count; public SyncThreadDemo1() { count = 0; } public void run() { synchronized(this) { for (int i = 0; i < 5; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * SyncThread1:0 * SyncThread1:1 * SyncThread1:2 * SyncThread1:3 * SyncThread1:4 * SyncThread2:5 * SyncThread2:6 * SyncThread2:7 * SyncThread2:8 * SyncThread2:9 */ public static void main(String[] args) { SyncThreadDemo1 syncThread = new SyncThreadDemo1(); Thread thread1 = new Thread(syncThread,"SyncThread1"); Thread thread2 = new Thread(syncThread, "SyncThread2"); thread1.start(); thread2.start(); }}
package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on 2020/6/24 10:53 * @description 锁不同的对象 */public class SyncThreadDemo2 implements Runnable { private static int count; public SyncThreadDemo2() { count = 0; } public void run() { synchronized(this) { for (int i = 0; i < 5; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * SyncThread2:0 * SyncThread1:1 * SyncThread2:2 * SyncThread1:2 * SyncThread2:3 * SyncThread1:4 * SyncThread2:5 * SyncThread1:5 * SyncThread1:6 * SyncThread2:6 * synchronized锁定的是对象,这时会有两把锁分别锁定syncThread1对象和syncThread2对象, * 而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行 */ public static void main(String[] args) { Thread thread1 = new Thread(new SyncThreadDemo2(),"SyncThread1"); Thread thread2 = new Thread(new SyncThreadDemo2(), "SyncThread2"); thread1.start(); thread2.start(); }}
package com.xiaobu.synchronizedTest;import java.util.concurrent.atomic.AtomicInteger;/** * @author xiaobu * @version JDK1.8.0_171 * @date on 2020/6/24 10:53 * @description */public class SyncThreadAtomicIntegerDemo implements Runnable { private static AtomicInteger count; public SyncThreadAtomicIntegerDemo() { count = new AtomicInteger(0); } @Override public void run() { synchronized(this) { for (int i = 0; i < 5; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count.incrementAndGet())); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * SyncThread1:1 * SyncThread2:2 * SyncThread1:3 * SyncThread2:4 * SyncThread1:5 * SyncThread2:6 * SyncThread1:7 * SyncThread2:8 * SyncThread1:9 * SyncThread2:10 * * 原本是线程不安全的 AtomicInteger是原子类 导致数据的安全性 */ public static void main(String[] args) { SyncThreadAtomicIntegerDemo syncThread = new SyncThreadAtomicIntegerDemo(); Thread thread1 = new Thread(new SyncThreadAtomicIntegerDemo(),"SyncThread1"); Thread thread2 = new Thread(new SyncThreadAtomicIntegerDemo(), "SyncThread2"); thread1.start(); thread2.start(); }}
二、多个线程访问synchronized和非synchronized代码块
package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on 2020/6/24 10:53 * @description * countAdd是一个synchronized的,printCount是非synchronized的。 * 从上面的结果中可以看出一个线程访问一个对象的synchronized代码块时, * 别的线程可以访问该对象的非synchronized代码块而不受阻塞。 */public class SyncThreadCounter implements Runnable { private int count; public SyncThreadCounter() { count = 0; } public void countAdd() { synchronized(this) { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } //非synchronized代码块,未对count进行读写操作,所以可以不用synchronized public void printCount() { for (int i = 0; i < 5; i ++) { try { System.out.println(Thread.currentThread().getName() + " count:" + count); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public void run() { String threadName = Thread.currentThread().getName(); if (threadName.equals("A")) { countAdd(); } else if (threadName.equals("B")) { printCount(); } } /** * B count:0 * A:0 * B count:1 * A:1 * B count:2 * A:2 * A:3 * B count:4 * A:4 * B count:5 */ public static void main(String[] args) { SyncThreadCounter counter = new SyncThreadCounter(); Thread thread1 = new Thread(counter, "A"); Thread thread2 = new Thread(counter, "B"); thread1.start(); thread2.start(); }}
三、指定要给某个对象加锁
当有一个明确的对象作为锁时,就可以用类似下面这样的方式写程序。
public void method3(SomeObject obj){ //obj 锁定的对象 synchronized(obj) { // todo }}
当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:
class Test implements Runnable{ private byte[] lock = new byte[0]; // 特殊的instance变量 public void method() { synchronized(lock) { // todo 同步代码块 } } public void run() { }}
说明:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
四、修饰一个方法
public synchronized void method(){ // todo}
<==>等价于
public void method(){ synchronized(this){ // todo }}
修饰静态方法
package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on 2020/6/24 10:53 * @description synchronized 修饰静态方法相当于锁的对象是类的实例,即锁定的是这个类的所有对象 */public class SyncThreadStaticDemo1 implements Runnable { private static int count; public SyncThreadStaticDemo1() { count = 0; } public static synchronized void method() { for (int i = 0; i < 5; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override public void run() { method(); } /** * SyncThread1:0 * SyncThread1:1 * SyncThread1:2 * SyncThread1:3 * SyncThread1:4 * SyncThread2:5 * SyncThread2:6 * SyncThread2:7 * SyncThread2:8 * SyncThread2:9 */ public static void main(String[] args) { SyncThreadStaticDemo1 syncThread = new SyncThreadStaticDemo1(); Thread thread1 = new Thread(syncThread,"SyncThread1"); Thread thread2 = new Thread(syncThread, "SyncThread2"); thread1.start(); thread2.start(); }}
五、修饰一个类
package com.xiaobu.synchronizedTest;/** * @author xiaobu * @version JDK1.8.0_171 * @date on 2020/6/24 10:53 * @description synchronized 修饰类,即锁定的是这个类的所有对象 */public class SyncThreadStaticDemo2 implements Runnable { private static int count; public SyncThreadStaticDemo2() { count = 0; } public static void method() { synchronized (SyncThreadStaticDemo2.class){ for (int i = 0; i < 5; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } @Override public void run() { method(); } /** * SyncThread1:0 * SyncThread1:1 * SyncThread1:2 * SyncThread1:3 * SyncThread1:4 * SyncThread2:5 * SyncThread2:6 * SyncThread2:7 * SyncThread2:8 * SyncThread2:9 */ public static void main(String[] args) { SyncThreadStaticDemo2 syncThread = new SyncThreadStaticDemo2(); Thread thread1 = new Thread(syncThread,"SyncThread1"); Thread thread2 = new Thread(syncThread, "SyncThread2"); thread1.start(); thread2.start(); }}
SyncThreadStaticDemo1和SyncThreadStaticDemo2是等价的
参考:
转载地址:http://yzgai.baihongyu.com/