java synchronized
一、简介
常用的有如下几种方式
synchronized(this)、synchronized(Object)与synchronized修饰静态方法、synchronized(class)
二、修饰本身对象
如下两种写法是具有一样的效果,都是锁住自己本身的对象,当同一对象多次调用时,同步锁会起作用。
1.synchronized代码块
写法一:
public synchronized void method() { // todo }
写法二:
public void method() { synchronized(this) { // todo } }
2.非synchronized代码块
class Counter implements Runnable{ private int count; public Counter() { 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(); } } }
调用代码
Counter counter = new Counter(); Thread thread1 = new Thread(counter, "A"); Thread thread2 = new Thread(counter, "B"); thread1.start(); thread2.start();
结果
A:0 B count:1 A:1 B count:2 A:2 B count:3 A:3 B count:4 A:4 B count:5
上面代码中countAdd是一个synchronized的,printCount是非synchronized的。从上面的结果中可以看出一个线程访问一个对象的synchronized代码块时,别的线程可以访问该对象的非synchronized代码块而不受阻塞。
三、同步一段代码
当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:
class Test implements Runnable { private byte[] lock = new byte[0]; // 特殊的instance变量 public void method() { synchronized(lock) { // todo 同步代码块 } } public void run() { } }
四、修饰类
如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁,那也就是说对任何对象都是同步的。
1.修饰类
class ClassName { public void method() { synchronized(ClassName.class) { // todo } } }
2.修饰静态方法
class SyncThread implements Runnable { public synchronized static void method() { //todo } }
参考:https://blog.csdn.net/luoweifu/article/details/46613015