17、使用synchronized(string)同步块时,要注意String常量池带来的例外

版权声明:版权归 爱装逼的文艺小青年所有 https://blog.csdn.net/toyota_rav4/article/details/85204066

导语:我们在使用synchronized(string)同步块时,要注意String常量池带来的例外。

在jvm中具有String常量池缓存的功能。

package com.demo1;

public class Run {
    public static void main(String[] args) {
        String a = "a";
        String b = "a";
        System.out.println(a == b);
    }
}

打印结果:

true

下面的例子,将说明String常量池带来的例外

package com.demo1;

public class MyObject {
    public void print(String stringParam){
        try {
            synchronized (stringParam) {
                while (true) {
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.demo1;

public class ThreadA extends Thread {
    private MyObject myObject;

    public ThreadA(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.print("str");
    }
}
package com.demo1;

public class ThreadB extends Thread {
    private MyObject myObject;

    public ThreadB(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.print("str");
    }
}
package com.demo1;

public class Run2 {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        ThreadB threadB = new ThreadB(myObject);
        threadA.setName("a");
        threadB.setName("b");
        threadA.start();
        threadB.start();
    }
}

输出结果:

a
a
a
a
a
a

因为ThreadA ThreadB持有相同的锁,导致线程B不能执行。这也就是String 常量池所带来的同步代码块的问题。一般不使用String作为锁对象。例如使用 new Object(),修改代码如下:

package com.demo1;

public class MyObject {
    public void print(Object obj){
        try {
            synchronized (obj) {
                while (true) {
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.demo1;

public class ThreadA extends Thread {
    private MyObject myObject;

    public ThreadA(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.print(new Object());
    }
}
package com.demo1;

public class ThreadB extends Thread {
    private MyObject myObject;

    public ThreadB(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.print(new Object());
    }
}
package com.demo1;

public class Run2 {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        ThreadB threadB = new ThreadB(myObject);
        threadA.setName("a");
        threadB.setName("b");
        threadA.start();
        threadB.start();
    }
}

输出结果:

a
b
a
b
a
b
a
b
a
b

很明显 a,b交替得到cpu资源。

猜你喜欢

转载自blog.csdn.net/toyota_rav4/article/details/85204066