前言:
在程序中,若存在多个线程同时操作共享变量,就会造成线程不安全,要保证多线程操作共享数据安全,必须加上互斥锁,同一时刻只有一个线程可以操作数据。
synchronized三种用法:
1.实例方法
2.静态方法
3.代码块
我们先写出代码,查看运行结果,然后再分析
1.实例方法
package com.xhx.java;
/**
* xuhaixing
* 2018/6/30 17:29
**/
public class SynchronizedMethod {
public synchronized void method1(){
System.out.println("method1--start");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("method1--end");
}
public synchronized void method2(){
System.out.println("method2--start");
System.out.println("method2--end");
}
public static void main(String[] args) {
final SynchronizedMethod sync = new SynchronizedMethod();
new Thread(() -> sync.method1()).start();
new Thread(() -> sync.method2()).start();
}
/**
* method1--start
* method1--end
* method2--start
* method2--end
*/
}
可以看出,对于同一个实例,方法的执行也是互斥的,锁的时当前实例对象
2.静态方法
package com.xhx.java;
/**
* xuhaixing
* 2018/6/30 17:29
**/
public class SynchronizedStaticMethod {
public static synchronized void method1(){
System.out.println("method1--start");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("method1--end");
}
public static synchronized void method2(){
System.out.println("method2--start");
System.out.println("method2--end");
}
public static void main(String[] args) {
new Thread(() ->
SynchronizedStaticMethod.method1()).start();
new Thread(() ->
SynchronizedStaticMethod.method2()).start();
}
/**
* method1--start
* method1--end
* method2--start
* method2--end
*/
}
类中的静态方法执行也是互斥的,锁的是Class
3.代码块
package com.xhx.java;
/**
* xuhaixing
* 2018/6/30 17:29
**/
public class SynchronizedBlock {
public void method1() {
System.out.println("method1--start");
try {
synchronized (this) {
System.out.println("method1--executing");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("method1--end");
}
public void method2() {
System.out.println("method2--start");
synchronized (this) {
System.out.println("method2--executing");
}
System.out.println("method2--end");
}
public static void main(String[] args) {
final SynchronizedBlock sync = new SynchronizedBlock();
new Thread(() -> sync.method1()).start();
new Thread(() -> sync.method2()).start();
}
/**
method1--start
method1--executing
method2--start
method1--end
method2--executing
method2--end
*/
}
执行到锁时,因为锁的都是this,所以代码块也是互斥的
有一种情况需要注意,如果线程A访问静态的synchronized方法,线程B访问非静态的synchronized方法,是允许的,因为它俩用的不是同一个锁。
在使用synchronized的时候,尽量降低加锁范围,能在代码段上加锁,就不要在方法上加锁。synchronized内部通过monitor来实现的,属于重量级锁。