美文网首页
synchronized踩坑

synchronized踩坑

作者: 忘净空 | 来源:发表于2017-07-25 10:19 被阅读85次

不要使用字符串常量作为对象锁去同步代码

synchronized是对象锁,但是对于这个Java内置的对象锁如果理解不深入可能就会踩到坑。请看下面的例子:

public class DeadLockDemo {

    private static String A = "A";
    private static String B = "B";

    public static void main(String[] args) {

            new DeadLockDemo().deadLock();
    }

    private void deadLock() {
            Thread t1 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                            synchronized (A) {
                                    try { Thread.currentThread().sleep(2000);
                                    } catch (InterruptedException e) {
                                            e.printStackTrace();
                                    }
                                    synchronized (B) {
                                            System.out.println("1");
                                    }
                            }
                    }
            });

            Thread t2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                            synchronized (B) {
                                    synchronized (A) {
                                            System.out.println("2");
                                    }
                            }
                    }
            });

            t1.start();
            t2.start();
    }

}

上面是一个死锁的例子,用来演示死锁是没有问题,但是大家有没有注意privat static String A = "A",它使用字符串常量作为对象锁,大家认为这个有问题吗?请看下面这个例子。

public class NotifyTest {

    private String flag = "true";

    class NotifyThread extends Thread {
        public NotifyThread(String name) {
            super(name);
        }

        public void run() {
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (flag) {
                //flag的对象变为false,对象发生改变
                flag = "false";
                flag.notifyAll();
            }
        }
    }

    class WaitThread extends Thread {
        public WaitThread(String name) {
            super(name);
        }

        public void run() {
            synchronized (flag) {
                while (flag.equals("true")) {
                    System.out.println(getName() + " begin waiting!");
                    long waitTime = System.currentTimeMillis();
                    try {
                        flag.wait();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    waitTime = System.currentTimeMillis() - waitTime;
                    System.out.println("wait time :" + waitTime);
                }
                System.out.println(getName() + " end waiting!");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Main Thread Run!");
        NotifyTest test = new NotifyTest();
        NotifyThread notifyThread = test.new NotifyThread("notify01");
        WaitThread waitThread01 = test.new WaitThread("waiter01");
        notifyThread.start();
        waitThread01.start();
    }

}

运行结果:
Main Thread Run!
waiter01 begin waiting!
Exception in thread "notify01" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at juc.NotifyTest$NotifyThread.run(NotifyTest.java:24)

为什么会出现上面的情况:问题主要是flag对象的引用发生了改变,我们如何选择synchoronize的锁呢,其实只要我们将flag换为javaBean就行,现在为了方便起见我们使用String数组private String flag[] = {"true"}这样也可以解决问题。例子如下:

package juc;

/**
 * Created by wjk on 2017/7/25.
 */
public class NotifyTest {

    private String flag[] = {"true"};

    class NotifyThread extends Thread {
        public NotifyThread(String name) {
            super(name);
        }

        public void run() {
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (flag) {
                //flag的对象变为false,对象发生改变
                flag[0] = "false";
                flag.notifyAll();
            }
        }
    }

    class WaitThread extends Thread {
        public WaitThread(String name) {
            super(name);
        }

        public void run() {
            synchronized (flag) {
                while (flag[0].equals("true")) {
                    System.out.println(getName() + " begin waiting!");
                    long waitTime = System.currentTimeMillis();
                    try {
                        flag.wait();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    waitTime = System.currentTimeMillis() - waitTime;
                    System.out.println("wait time :" + waitTime);
                }
                System.out.println(getName() + " end waiting!");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Main Thread Run!");
        NotifyTest test = new NotifyTest();
        NotifyThread notifyThread = test.new NotifyThread("notify01");
        WaitThread waitThread01 = test.new WaitThread("waiter01");
        notifyThread.start();
        waitThread01.start();
    }

}

相关文章

  • synchronized踩坑

    不要使用字符串常量作为对象锁去同步代码 synchronized是对象锁,但是对于这个Java内置的对象锁如果理解...

  • JavaScrip-StepPitGuide《JavaScrip

    《JavaScript踩坑指南》JavaScrip-StepPitGuide? 《JavaScript踩坑指南》 ...

  • 算法踩坑6-二叉搜索树排序

    背景 接上面五篇文章算法踩坑-快速排序 算法踩坑2-插入排序 算法踩坑3-堆排序 算法踩坑4-冒泡排序 ...

  • 算法踩坑5-归并排序

    背景 接上面四篇文章算法踩坑-快速排序 算法踩坑2-插入排序 算法踩坑3-堆排序 算法踩坑4-冒泡排序 来...

  • D1094:踩坑的价值最大化

    是人就会踩坑,不踩坑理论上就不属于人类,踩坑是人之常情,能回头站在坑边反思,才是对踩过的的坑价值最大化的体现,要不...

  • 交互设计师所要避免的几个坑

    前言 工作中难免会踩到几个坑,即使现在不踩以后还会踩,只有踩过才会深刻记住,踩过说明爱过!但是踩过的坑必须把坑填满...

  • 踩坑,使用cocoaPods import导入时没有提示的解决办

    续上篇写的,踩坑,cocoaPods ---- framework not found Pods之后 ,又踩坑了。...

  • 2020-10-19随笔 踩坑0传值

    踩坑:当值传入0时,if条件判断时候会自己转换,记录踩坑。

  • 随笔

    读书啊,就是一个坑踩完了又掉进另一个坑,先说踩读书没用的坑,爬出来了,再踩读书要多的坑,之后再踩读书要精啊,读书要...

  • PHP中的数据类型

    一说到数据类型,这个坑就太多了,多到有哪些坑,有多少坑,不知道自己还会踩哪些坑,以及踩过的坑还会不会再踩,我对...

网友评论

      本文标题:synchronized踩坑

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