美文网首页
锁对象的改变

锁对象的改变

作者: 迷糊小生 | 来源:发表于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线程之间是完全同步的,由此我们在写多线程并发代码的时候,切记不要在线程内部将对象锁给改变(特殊场景例外)

    相关文章

      网友评论

          本文标题:锁对象的改变

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