美文网首页
多线程安全 synchronized使用

多线程安全 synchronized使用

作者: 向上_d821 | 来源:发表于2019-09-26 16:05 被阅读0次

    我们在写一个单例模式的管理类时都会这样写

    public class ConfigManager {
        private static ConfigManager instance;
        private ConfigManager(){}
        public static synchronized ConfigManager getInstance(){
            if(instance==null){
                instance=new ConfigManager();
            }
            return instance;
        }
        public static ConfigManager getInstanceUseDoubleLock(){
            if(instance==null){
                synchronized (ConfigManager.class){
                    if(instance==null){
                        instance=new ConfigManager();
                    }
                }
            }
            return instance;
        }
    }
    

    上面的线程安全有两种写法,一个是在方法上加synchronized,一个是在代码块中加上synchronized,这两个有方法加上synchronized有什么用,又有什么区别呢?
    1.一个类如下:

    public class UserManager {
        private User user;
        public UserManager(User user) {
            this.user = user;
        }
        public void updateUser(User newUser){
            user.setName(newUser.getName());
            user.setGender(newUser.getGender());
        }
    }
    

    2.创建一个User类

    public class User {
        private String name;
        private String gender;
        public User() {}
        public User(String name, String gender) {
            this.name = name;
            this.gender = gender;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getGender() {
            return gender;
        }
        public void setGender(String gender) {
            this.gender = gender;
        }
        @Override
        public String toString() {
            return "User{" + "name='" + name + '\'' + ", gender='" + gender + '\'' + '}';
        }
    }
    

    3.开启两个线程

     private User user;
     private UserManager userManager;
     user = new User();
     userManager = new UserManager(user);
    //线程一
            new Thread(new Runnable() {
                @Override
                public void run() {
                    User user1=new User("Tom","男");
                    userManager.updateUser(user1);
                }
            }).start();
            //线程二
            new Thread(new Runnable() {
                @Override
                public void run() {
                    User user2=new User("凤姐","女");
                    userManager.updateUser(user2);
                }
            }).start();
          Log.e("user----",user.toString());   
            
    

    4.结果:
    线程一:name="Tom";
    线程二:name="凤姐";
    线程二:gender="女";
    线程一:gender="男";
    结果:name="凤姐",gender="男"

    结果数据混乱了

    使用synchronized解决方法

     public synchronized void updateUser(User newUser){
            user.setName(newUser.getName());
            user.setGender(newUser.getGender());
        }
    

    有一个场景:新增一个printUser方法

    public synchronized void updateUser(User newUser){
            user.setName(newUser.getName());
            user.setGender(newUser.getGender());
        }
    public synchronized void printUser(){
            Log.e("UserManager--","name:"+user.getName()+"--gender:"+user.getGender());
        }
    

    updateUser和printUser方法上都加上锁synchronized,这个时候updateUser方法调用时,线程中printUser方法不会调用的,可以确保我的信息写入完之后,我才能读取,

    现在有一个场景需求:我想新加一个方法,两个方法同时进行,互不影响

    如下:

    public class UserManager {
        private User user;
        private final Object monitor2=new Object();
        public UserManager(User user) {
            this.user = user;
        }
        public synchronized void updateUser(User newUser){
            user.setName(newUser.getName());
            user.setGender(newUser.getGender());
        }
        public synchronized void printUser(){
            Log.e("UserManager--","name:"+user.getName()+"--gender:"+user.getGender());
        }
        /**
         * 现在新增的其他方法也加上锁synchronized,这样会导致其他必须在上面的updateUser调用完毕才能执行,
         * 这样我想调用otherMethod必须在此之后,不符合实际
         */
        public void otherMethod(){
            synchronized (monitor2){
                Log.e("UserManager--","同时调用第二个方法");
            }
        }
    }
    
    

    synchronized在两个方法加入的位置不一样,有什么区别呢?

    updateUser()和printUser()方法在方法上加上锁,此时它们有系统提供的默认管理者monitor在管理,当updateUser()进去线程管理后,printUser()是不能进去了,所以这个方法不调用, 而otherMethod()方法在代码块里添加一个自己创建的monitor2,会管理自己的方法,所以不受上面的影响。

    注意:线程不安全是因为数据读取中,进行write写入或者write写入中有读取,如果两个线程都是读取不会存在线程安全问题

    相关文章

      网友评论

          本文标题:多线程安全 synchronized使用

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