多线程之详解synchronized关键字

相信学习过多线程的童鞋多多少少都会用到 synchronized 关键字, 加了这个, 妈妈再也不用担心我的代码不同步了。真的是这样的么?
我们看一下下面的代码:

/**
 * 验证同步锁锁住的是什么
 * <p>
 * 
 * @author YangHang
 * @Date 2019年1月4日 下午11:38:01
 *
 */
public class SynchronizedConfirmation {

    /**
     *
     */
    public static void main(String[] args) {
        NotSafeObject notSafeObject = new NotSafeObject();
        NotSafeObject notSafeObject1 = new NotSafeObject();

        Thread thread1 = new MyThread1(notSafeObject);

        Thread thread2 = new MyThread2(notSafeObject1);

        thread1.start();
        thread2.start();

    }

}

class NotSafeObject {

    public synchronized void print() {
        for (int i = 1; i <= 100; i++) {
            out.println(Thread.currentThread().getName() + " A: " + i);
        }
    }

    public synchronized void otherPrint() {
        for (int i = 1; i <= 100; i++) {
            out.println(Thread.currentThread().getName() + " B" + i);
        }
    }

}

/**
 * 自己的线程类1
 *
 */
class MyThread1 extends Thread {

    private NotSafeObject notSafeObject;

    // 有参构造...
    public MyThread1(NotSafeObject notSafeObject) {
        this.notSafeObject = notSafeObject;
    }

    @Override
    public void run() {
        notSafeObject.print();
    }

}

/**
 * 自己的线程类2
 *
 */
class MyThread2 extends Thread {

    private NotSafeObject notSafeObject;

    // 有参构造...
    public MyThread2(NotSafeObject notSafeObject) {
        this.notSafeObject = notSafeObject;
    }

    @Override
    public void run() {
        notSafeObject.print();
    }

}

点击运行得到的结果是:
在这里插入图片描述
我们可以看到, 运行的结果仍然是两个线程杂乱无章的交替运行中。似乎, 同步关键字并没有起作用。这是因为, 我们直接在方法上加 synchronized 关键字, 相当于用当前的对象给这段代码加了锁, 锁住的是当前这个对象。下一个线程会找当前的对象是否有被上锁, 有的话等待, 没有的话执行代码。上面的代码是有两个对象当锁, 自然不会起到同步的效果。那么, 要怎么实现全局锁呢(就是怎么来我都锁你)。两种方式加锁一种是在方法上用static synchronized加锁, 如下图:

class NotSafeObject {

    public static synchronized void print() {
        for (int i = 1; i <= 100; i++) {
            out.println(Thread.currentThread().getName() + " A: " + i);
        }
    }

    public static synchronized void otherPrint() {
        for (int i = 1; i <= 100; i++) {
            out.println(Thread.currentThread().getName() + " B" + i);
        }
    }

}

静态的同步, 就相当于用这个类对象加锁, 类对象是唯一的, 再来一个线程朋友来判断, 怎么的这个类对象都在上一个线程朋友手里, 因为全天下就这一个类对象。再有就是

     public void print() {
        synchronized (NotSafeObject.class) {
            for (int i = 1; i <= 100; i++) {
                out.println(Thread.currentThread().getName() + " A: " + i);
            }
        }

    }

道理等同, 相当于也是用类对象锁住的。
以上代码的运行结果:
在这里插入图片描述
同步达成。
总结: synchronized 单独放到方法上或者 synchronized (this)相当于用当前的对象上锁, static synchronized 和 synchronized (***.class)相当于用类对象上锁, 不同的对象可能锁不住。但是类对象必然能锁住, 叫全局锁。
思考: 另外一个方法用同一个对象锁锁住了, 是不是也被同步了。 答案是肯定的, 因为锁的是对象, 我们是判断对象有没有锁来识别代码要不要往下走的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员大航子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值