Synchronize线程同步关键词,此关键词会以可重入的独占锁的形式使用,根据synchronize使用的四种方式不同锁定的对象或者类也不同。
举个例子:几个乌鸦给瓶子里面丢石头喝水的故事 一次只能丢一个石头,其后所有的丢石头操作都必须得等待前面那只乌鸦将石头丢进瓶子里面才行,其他乌鸦在丢进瓶子的时候可以做其他事情,比如说捡石头或者寻找其他水源,但是一次只能有一只乌鸦能够将石头丢进瓶口。
Synchronize关键词四种使用方式
//第一种方式 锁定的是调用此方法的对象
public synchronized void Synchronized() {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
//第二种方式 synchronize锁static method 是以锁当前类的形式
public synchronized static void SynchronizedStaticMethod() {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
//第三种方式是在代码中锁定对象 锁的是调用此Synchronize方法的对象
public void SynchronizedObject(Object object) {
synchronized (object) {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
}
//第四种方式是在方法代码中锁定this 锁的是当前类对象
//锁this详解 一个时间段只能有一个线程拿到锁 ,其他线程访问此方法的时候都必须得等待前面那个线程执行完
//即乌鸦在丢石头进瓶子的过程中,其他乌鸦可以去其他地方看有没有其他喝水的地方
//上面这个例子就是说明在访问synchronize锁定的方法时 可以去访问其他方法
public void SynchronizedThis() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
}
完整实例:
/**
* @ClassName SynchronizedUseFourMenthod
* @Description TODO
* @Author huangwb
* @Date 2019-02-26 21:15
* @Version 1.0
**/
/**
*
*/
public class SynchronizedUseFourMenthod {
private static Integer synchronizedCount = 0;
//第一种方式 锁定的是调用此方法的对象
public synchronized void Synchronized() {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
//第二种方式 synchronize锁static method 是以锁当前类的形式
public synchronized static void SynchronizedStaticMethod() {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
//第三种方式是在代码中锁定对象 锁的是调用此Synchronize方法的对象
public void SynchronizedObject(Object object) {
synchronized (object) {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
}
//第四种方式是在方法代码中锁定this 锁的是当前类对象
//锁this详解 一个时间段只能有一个线程拿到锁 ,其他线程访问此方法的时候都必须得等待前面那个线程执行完
//即乌鸦在丢石头进瓶子的过程中,其他乌鸦可以去其他地方看有没有其他喝水的地方
//上面这个例子就是说明在访问synchronize锁定的方法时 可以去访问其他方法
public void SynchronizedThis() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
}
}
//如果synchronized打在静态方法上锁定的就是类对象 无论实例化几个类都是属于同一个类对象都只能有一个线程来访问该类
//如果synchronized无论打在普通方法上还是代码中锁定的都是对象,而不是把一段代码锁定 即同步方法很可能被其他线程的对象访问,就是当我实例了两个对象 lock1,lock2
//lock1访问方法的时候锁定了当前对象的访问 其他线程还是能够继续访问这个synchronized同步的方法
}
总结:
如果synchronized打在静态方法上锁定的就是类对象 无论实例化几个类都是属于同一个类对象都只能有一个线程来访问该类
如果synchronized无论打在普通方法上还是代码中锁定的都是对象,而不是把一段代码锁定 即同步方法很可能被其他线程的对象访问。也就是说当我实例了两个对象 lock1,lock2,lock1访问方法的时候锁定了当前对象的访问其他线程还是能够继续访问这个synchronized同步的方法,这个时候就会造成数据的混乱。
为什么我会总结这样呢,大家可以看看下面这个案例,这个案例说明了这种总结的情况给各位加深印象。
/**
* @ClassName SynchronizedTest
* @Description TODO
* @Author huangwb
* @Date 2019-02-26 21:40
* @Version 1.0
**/
public class SynchronizedTest {
static class InnerClass implements Runnable{
private Integer synchronizedCount = 0;
public Integer SynchronizedObject() {
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"我获取到了synchronized同步的锁了可以执行了");
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"我执行完毕了");
}
return synchronizedCount;
}
@Override
public void run() {
System.out.println(SynchronizedObject());
}
}
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
InnerClass innerClass2 = new InnerClass();
new Thread(innerClass).start();
new Thread(innerClass2).start();
}
}
/**
* @ClassName SynchronizedTest2
* @Description TODO
* @Author huangwb
* @Date 2019-02-26 21:47
* @Version 1.0
**/
public class SynchronizedTest2 {
static class InnerClass implements Runnable {
private static Integer synchronizedCount = 0;
public synchronized static Integer SynchronizedObject() {
System.out.println(Thread.currentThread().getName() + "我获取到了synchronized同步的锁了可以执行了");
for (int i = 0; i < 200; i++) {
synchronizedCount++;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "我执行完毕了");
return synchronizedCount;
}
@Override
public void run() {
System.out.println(SynchronizedObject());
}
}
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
InnerClass innerClass2 = new InnerClass();
new Thread(innerClass).start();
new Thread(innerClass2).start();
}
}
如果想了解Synchronized的原理可以去看看这篇博文 写得非常不错