• Synchronized 锁的错误使用方式及如何解决


    synchronized关键字,一般称之为”同步锁“,用它来修饰需要同步的方法和需要同步代码块,默认是当前对象作为锁的对象。

    同步锁锁的是同一个对象,如果对象发生改变,则锁会不生效。

    锁失败的代码:

    public class IntegerSynTest {
    
        //线程实现Runnable接口
        private static class Worker implements Runnable{
    
            private Integer num;
    
            public Worker(Integer num){
                this.num=num;
            }
            @Override
            public void run() {
                
                synchronized (num){
                    Thread thread = Thread.currentThread();
                    //System.identityHashCode:返回原生的hashCode值,不管Object对象是被重写;空引用的哈希代码为零
                    System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
                    num++;
                    System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
                }
            }
    
            public static void main(String[] args) {
                Worker worker = new Worker(1);
                for (int i = 0; i < 5; i++) {
                    new Thread(worker).start();
                }
            }
        }
    }

    锁失败的运行结果:

    锁失败的原因:

    1.num++  的  .class  实现是这样的  Integer integer1 = this.num, integer2 = this.num = Integer.valueOf(this.num.intValue() + 1);

    2. 查看 Integer.valueOf() 的源代码

     这时发现,它是重新 new 出一个新的 Integer,这样的话,每 ++ 一次,那么就会产生一个新的对象,而Synchronize锁是锁同一个对象,当锁不同对象时,则会锁失败。

    解决方法:

    Synchronized 同步锁只要锁的对象不发生改变即可,那么由此只需要声明一个对象,不修改它,锁这一个对象即可(还有其他方法暂不一一列举,以后也不会列举了)。

    锁成功的代码

    public class IntegerSynTest {
    
        //线程实现Runnable接口
        private static class Worker implements Runnable{
    
            private Integer num;
            /**
             *  ---重点看这里---
             *  声明要锁的对象
             *  ---重点看这里---
             */
            private Object object = new Object();
    
            public Worker(Integer num){
                this.num=num;
            }
            @Override
            public void run() {
                //修改锁对象
                synchronized (num){
                    Thread thread = Thread.currentThread();
                    //System.identityHashCode:返回原生的hashCode值,不管Object对象是被重写;空引用的哈希代码为零
                    System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
                    num++;
                    System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
                }
            }
    
            public static void main(String[] args) {
                Worker worker = new Worker(1);
                for (int i = 0; i < 5; i++) {
                    new Thread(worker).start();
                }
            }
        }
    }

    锁成功的运行结果:

  • 相关阅读:
    3、spring注解注入
    2、spring注入のArrayList数组对象注入方式
    1、基本知识
    1、log4j的配置与使用
    3、在Eclipse中使用JUnit4进行单元测试(高级篇)
    2、在Eclipse中使用JUnit4进行单元测试(中级篇)
    1、JUnit4简介
    使用BroadcastReceiver实现系统对手机电量进行提示
    使用BroadcastReceiver监听系统接收的短信
    使用BroadcastReceiver实现开机自动运行的Service
  • 原文地址:https://www.cnblogs.com/mjtabu/p/12702721.html
Copyright © 2020-2023  润新知