Java并发之Synchronize关键词的使用

    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的原理可以去看看这篇博文 写得非常不错

https://www.cnblogs.com/mingyao123/p/7424911.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

难搞哦!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值