版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangsweet1991/article/details/83824856
synchronized有四种用法:
1、修饰普通方法与静态方法,放在范围操作符(public等)之后,返回类型声明(void等)之前。
2、对某一代码块使用,synchronized后跟括号,括号里是变量、对象、类。
修饰普通方法与静态方法,那么他们的锁分别是什么呢?让我们一起验证一下。
不加锁
public class SynWork {
private int index;
public void synMethod1(int index) {
for (int i = 0; i < 3; i++) {
try {
this.index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + this.index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void synMethod2(int index) {
for (int i = 0; i < 3; i++) {
try {
this.index = index;
System.out.println("synMethod2:" + Thread.currentThread().getName() + ":" + this.index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class SynTest {
public static void main(String[] args) {
SynWork synWork = new SynWork();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(1);
}
}, "T1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(2);
}
}, "T2");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod2(30);
}
}, "T3");
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod2(40);
}
}, "T4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
运行结果:
synMethod1:T2:2
synMethod2:T4:40
synMethod2:T3:30
synMethod1:T1:2
synMethod2:T3:30
synMethod1:T1:1
synMethod2:T4:40
synMethod1:T2:2
synMethod1:T2:30
synMethod1:T1:30
synMethod2:T3:30
synMethod2:T4:30
枷锁后
public class SynWork {
private int index;
public synchronized void synMethod1(int index) {
for (int i = 0; i < 3; i++) {
try {
this.index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + this.index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void synMethod2(int index) {
for (int i = 0; i < 3; i++) {
try {
this.index = index;
System.out.println("synMethod2:" + Thread.currentThread().getName() + ":" + this.index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
synMethod1:T1:1
synMethod1:T1:1
synMethod1:T1:1
synMethod2:T4:40
synMethod2:T4:40
synMethod2:T4:40
synMethod1:T2:2
synMethod1:T2:2
synMethod1:T2:2
synMethod2:T3:30
synMethod2:T3:30
synMethod2:T3:30
继续验证
public class SynWork {
private static int _index;
public synchronized void synMethod1(int index) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void synMethod2(int index) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod2:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class SynTest {
public static void main(String[] args) {
SynWork synWork = new SynWork();
SynWork synWork2 = new SynWork();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(1);
}
}, "T1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synWork2.synMethod1(2);
}
}, "T2");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod2(30);
}
}, "T3");
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
synWork2.synMethod2(40);
}
}, "T4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
运行结果:
synMethod1:T1:2
synMethod1:T2:2
synMethod1:T2:2
synMethod1:T1:1
synMethod1:T2:2
synMethod1:T1:2
synMethod2:T3:30
synMethod2:T4:30
synMethod2:T3:30
synMethod2:T4:40
synMethod2:T3:30
synMethod2:T4:40
由此可知修饰普通方法的锁是方法所在类的对象。
在一个类里,同时修饰普通方法和静态方法
public class SynWork {
private static int _index;
// 普通方法
public synchronized void synMethod1(int index) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 静态方法
public synchronized static void synMethod2(int index) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod2:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class SynTest {
public static void main(String[] args) {
SynWork synWork = new SynWork();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(1);
}
}, "T1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(2);
}
}, "T2");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
SynWork.synMethod2(30);
}
}, "T3");
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
SynWork.synMethod2(40);
}
}, "T4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
运行结果:
synMethod1:T1:1
synMethod2:T3:30
synMethod2:T3:30
synMethod1:T1:30
synMethod2:T3:30
synMethod1:T1:30
synMethod1:T2:2
synMethod2:T4:40
synMethod1:T2:2
synMethod2:T4:40
synMethod2:T4:2
synMethod1:T2:2
继续验证
public class SynWork {
private static int _index;
// 普通方法
public void synMethod1(int index) {
synchronized (SynWork.class) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 静态方法
public synchronized static void synMethod2(int index) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod2:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class SynTest {
public static void main(String[] args) {
SynWork synWork = new SynWork();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(1);
}
}, "T1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(2);
}
}, "T2");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
SynWork.synMethod2(30);
}
}, "T3");
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
SynWork.synMethod2(40);
}
}, "T4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
运行结果:
synMethod1:T1:1
synMethod1:T1:1
synMethod1:T1:1
synMethod2:T4:40
synMethod2:T4:40
synMethod2:T4:40
synMethod1:T2:2
synMethod1:T2:2
synMethod1:T2:2
synMethod2:T3:30
synMethod2:T3:30
synMethod2:T3:30
由此可知,修饰静态方法和普通方法不是同一个锁,静态方法的锁是方法所在的类,即SynWork.class
synchronized修饰代码块
public class SynWork {
public static int _index;
// 普通方法
public void synMethod1(int index) {
synchronized (SynWork.class) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 静态方法
public synchronized static void synMethod2(int index) {
for (int i = 0; i < 3; i++) {
try {
_index = index;
System.out.println("synMethod2:" + Thread.currentThread().getName() + ":" + _index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Syn2Work {
// 普通方法
public void synMethod1(int index) {
synchronized (SynWork.class) {
for (int i = 0; i < 3; i++) {
try {
SynWork._index = index;
System.out.println("synMethod1:" + Thread.currentThread().getName() + ":" + SynWork._index);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class SynTest {
public static void main(String[] args) {
SynWork synWork = new SynWork();
Syn2Work syn2Work = new Syn2Work();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synWork.synMethod1(1);
}
}, "T1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
syn2Work.synMethod1(2);
}
}, "T2");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
SynWork.synMethod2(30);
}
}, "T3");
thread1.start();
thread2.start();
thread3.start();
}
}
运行结果:
synMethod1:T1:1
synMethod1:T1:1
synMethod1:T1:1
synMethod2:T3:30
synMethod2:T3:30
synMethod2:T3:30
synMethod1:T2:2
synMethod1:T2:2
synMethod1:T2:2
结论:
1、synchronized修饰普通方法时,锁的是方法所在类的对象,等同于synchronized(this){}。
2、synchronized修饰static方法时,锁的是方法所在类的class,等同于synchronized(类的clas){}。
3、synchronized修饰代码块时,锁是括号里的参数,括号中的参数一致时(==),则会形成互斥。
4、在使用synchronized时,用代码块更灵活,尽量缩小其影响范围