美文网首页
锁对象的改变

锁对象的改变

作者: 迷糊小生 | 来源:发表于2019-03-29 20:36 被阅读0次

在前面学习完多线程的synchronized对象锁之后,不禁思考到,如果当某一线程获得某对象的对象锁后,在其内部锁对象发生了改变,这样的话对象锁还会起到作用么?

下面让我们来写个Demo测试一下:

package other.thread5;

public class DemoService {

    private String lock = "123";
    
    public void test() {
        synchronized (lock) {
            try {
                System.out.println(Thread.currentThread().getName() + "==start==" + System.currentTimeMillis());
                lock = "234";
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "==end==" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        
        }
    }
    
}

首先我们创建了DemoService并且在其内部将lock改变。

public class ThreadA extends Thread{

    private DemoService service;
    public ThreadA(DemoService service) {
        this.service = service;
    }
    
    @Override
    public void run() {
        service.test();
    }
}
public class ThreadB extends Thread{

    private DemoService service;
    public ThreadB(DemoService service) {
        this.service = service;
    }
    
    @Override
    public void run() {
        service.test();
    }
}

两个简单的线程调用此方法。

public class Test {
    public static void main(String[] args) {
        try {
            DemoService service = new DemoService();
            ThreadA threadA = new ThreadA(service);
            threadA.setName("A");
            ThreadB threadB = new ThreadB(service);
            threadB.setName("B");
            threadA.start();
            Thread.sleep(200);
            threadB.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
image.png

看到此结果,明显的可以看出来线程不同步了。
让我们分析一下,当线程A首先获得了lock(123)并且进入到了同步代码块的内部,并且在其内部lock(234)对象发生了改变,然后B线程在test()方法内部也获取了一把lock(234),由于和线程A的lock(123)完全的不一致,所以B线程也就轻而易举的进入到了同步代码块里面,造成了线程不同步的结果。

那么问题来了,如果线程A和线程B同时进入到了test()方法内部,并且锁对象尚未作出改变,那么线程是否会同步呢?

下面让我们再来试验一下,将main方法中的线程睡眠200ms给去掉:

public class Test {
    public static void main(String[] args) throws InterruptedException {
        DemoService service = new DemoService();
        ThreadA threadA = new ThreadA(service);
        threadA.setName("A");
        ThreadB threadB = new ThreadB(service);
        threadB.setName("B");
        threadA.start();
        threadB.start();
    }
}
image.png

明显的可以看到AB线程之间是完全同步的,由此我们在写多线程并发代码的时候,切记不要在线程内部将对象锁给改变(特殊场景例外)

相关文章

  • 锁对象的改变

    在前面学习完多线程的synchronized对象锁之后,不禁思考到,如果当某一线程获得某对象的对象锁后,在其内部锁...

  • 锁对象改变引发的线程问题

    Java多线程锁对象的改变 用lock获取锁对象,当lock被修改以后,会产生是一把新的锁,另一个线程获取锁对象时...

  • 2.2.16锁对象的改变

    在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间...

  • synchronized的锁对象改变问题

    大家都知道synchronized是一个对象锁,所以当对象变化时,锁就会消失,就会没有同步效果。 请看下面的问题:...

  • 乐观锁悲观锁

    乐观锁悲观锁: 悲观 :每次在拿数据的时候都会上锁。开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之...

  • synchronized笔记

    从被锁对象的性质上来说,synchronized加的锁分两种:实例对象锁和class对象锁。实例对象锁 这两种方式...

  • synchronized和lock简单理解

    synchronized(同步锁) 思考:锁什么?锁对象 可能锁对象包括:this,临界资源对象(所有线程可能访问...

  • synchronized 修饰静态方法、普通方法与代码块的区别

    概念: 类锁:所有对象共用一个锁 对象锁:一个对象一把锁,多个对象多把锁。 一、synchronized修饰普通方...

  • 05.锁机制和条件对象简述

    Java的锁机制主要分内置锁(隐式锁)和显式锁。 内置锁 Java每个对象都有一个内置的锁对象,这些锁对象不需要显...

  • java类锁和对象锁

    java对象锁有两种:对象锁、类锁。 对象锁:在非静态方法上加锁。声明了一个对象锁。类锁:在静态方法上加锁,声明了...

网友评论

      本文标题:锁对象的改变

      本文链接:https://www.haomeiwen.com/subject/hywrbqtx.html