`

关于线程安全的一些小问题

    博客分类:
  • java
 
阅读更多

 Person 类代码如下

public class Person {
    private int age;
    
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


}

 

public class Easy {

    private Person person = new Person();

    private static volatile Easy easy = null;

    private Easy() {
    }


    public static Easy instance() {
        if (easy == null) {
            synchronized (Easy.class) {
                if (easy == null) {
                    easy = new Easy();
                }
            }
        }
        return easy;
    }


    public void printPerson() {
        System.out.println(person);
    }


    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Easy.instance().printPerson();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Easy.instance().printPerson();
            }
        }).start();
    }
}

运行结果:

com.example.task.Person@6ab31cd3
com.example.task.Person@6ab31cd3

典型的火车买票的代码,这里这个person是线程共享的,存在堆内存中。

 

 

public class Easy {

    private Person person = null;

    private static volatile Easy easy = null;

    private Easy() {
    }

    public static Easy instance() {
        if (easy == null) {
            synchronized (Easy.class) {
                if (easy == null) {
                    easy = new Easy();
                }
            }
        }
        return easy;
    }


    public void printPerson() {
        System.out.println(person);
        person = new Person();
        System.out.println(person);
    }


    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run() {
               Easy.instance().printPerson();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Easy.instance().printPerson();
            }
        }).start();
    }
}

 运行结果:

null
com.example.task.Person@28979470
com.example.task.Person@28979470
com.example.task.Person@26507f12

 

从这里看到,如果在线程一中对成员变量进行赋值,切换到线程二的时候引用还是线程一的。

 

 

对于下面这段代码,为什么永远是同一个对象呢

 @Autowired
 private DialogueManager dialogueManager;

 这是因为工厂(spring工厂)获取的永远是用一个对象,使用代码可以这样表示

 

 

package com.example.task;

public class Person {
    private static volatile Person person = null;

    private Person() {
    }

    public static Person instance() {
        if (person == null) {
            synchronized (Person.class) {
                if (person == null) {
                    person = new Person();
                }
            }
        }
        return person;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private int age;
}

 

package com.example.task;


public class Easy {

    private Person person = null;

    private static volatile Easy easy = null;

    private Easy() {
    }


    public static Easy instance() {
        if (easy == null) {
            synchronized (Easy.class) {
                if (easy == null) {
                    easy = new Easy();
                }
            }
        }
        return easy;
    }


    public void printPerson() {
        System.out.println(person);
        person = Person.instance();
        System.out.println(person);
    }


    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run() {
               Easy.instance().printPerson();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Easy.instance().printPerson();
            }
        }).start();
    }
}

 运行结果:

 

null
com.example.task.Person@4f114b68
com.example.task.Person@4f114b68
com.example.task.Person@4f114b68

 

 

分享到:
评论

相关推荐

    servlet线程安全问题

    Servlet 线程安全问题 Servlet 线程安全问题是指在使用 Servlet 编程时,如果不注意多线程安全性问题,可能会导致难以发现的错误。Servlet/JSP 技术由于其多线程运行而具有很高的执行效率,但这也意味着需要非常...

    关于如何解决HashMap线程安全问题的介绍

    4. 避免在多线程环境中直接使用HashMap:如果你确定不需要在多线程环境下共享HashMap,那么可以考虑局部变量的方式,只在单个线程中使用HashMap,这样就无需担心线程安全问题。 总结起来,理解HashMap的线程不安全...

    servlet与Struts action线程安全问题分析

    Servlet和Struts Action是两种常见的Java Web开发组件,它们在多线程环境下运行时可能存在线程安全问题。线程安全是指在多线程环境中,一个类或者方法能够正确处理多个线程的并发访问,保证数据的一致性和完整性。 ...

    C#多线程List的非线程安全性

    本文将深入探讨在多线程环境中使用List时遇到的非线程安全问题,并提供相应的解决方案和最佳实践。 List是.NET框架中常用的一个动态数组,它提供了方便的增删改查操作。然而,List并未设计为线程安全的容器,这意味...

    C++线程安全问题及解决方法,C++智能指针

    内容概要:文章内容从原子性、可见性、有序性三个方面介绍C++线程安全问题的原因。通过原子操作、线程同步如互斥锁、读写锁、条件变量、信号量等方法解决C++线程安全问题。同时介绍了线程安全的单例,饿汉模式和懒汉...

    浅谈C#跨线程调用窗体控件(比如TextBox)引发的线程安全问题

    浅谈C#跨线程调用窗体控件引发的线程安全问题 C#跨线程调用窗体控件时可能会引发线程安全问题,例如当多个线程操作同一个控件时,该控件可能会进入不一致的状态,出现争用情况和死锁等问题。因此,确保以线程安全...

    unix_linux线程安全问题

    多线程编程带来的并发执行是其与生俱来的优势,但同时也引入了一系列的问题,尤其是线程安全问题。 线程安全问题主要来源于多个线程对共享资源的访问。如果多个线程同时访问同一个资源,且没有适当的同步机制,就...

    CVI 线程锁、线程安全变量实例

    在计算机编程领域,尤其是涉及到实时系统和并发编程时,线程锁和线程安全变量是至关重要的概念。LabWindows/CVI是一种流行的交互式C开发环境,特别适合于开发科学和工程应用。本实例将深入探讨如何在LabWindows/CVI...

    Stack 线程安全问题

    栈的线程安全问题 的解决代码 push pop synchronized THread

    java线程安全测试

    以下是一些常见的线程安全问题和解决策略: 1. 数据竞争:当两个或更多线程同时修改一个共享变量时,可能会导致数据不一致。解决方法是使用synchronized或java.util.concurrent包中的工具类,如AtomicInteger、...

    c# 线程安全队列的用法原理及使用示例

    什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等...

    线程通信安全问题

    线程通信安全问题是指在多线程环境下,如何保证多个线程对共享资源进行访问时的正确性和一致性。在这个场景下,我们主要探讨的是Java中的线程等待唤醒机制,这是一个用于解决线程同步问题的关键工具。 首先,我们要...

    Java多线程 - (一) 最简单的线程安全问题

    本篇文章将深入探讨“最简单的线程安全问题”,并结合相关源码和工具来帮助理解。线程安全问题通常涉及到多个线程对共享资源的访问,如果管理不当,可能会导致数据不一致、死锁等问题。 首先,我们需要了解什么是...

    构建线程安全应用程序

    在实际编码中,线程安全涉及多个方面,比如同步与互斥、线程干扰、活性问题等。同步是一种策略,用来协调多个线程访问共享资源的时序,确保数据的一致性。常见的同步机制有互斥锁(mutexes)、条件变量(condition ...

    验证QList线程安全性的小程序

    申明:不是原创,不是原创,只是转载。 这是一个来自网上的例子 ...用于测试QList的线程安全性,因原作者只给出源代码,没有给出测试结果,这里生成一个QT工程,打开即可编译,内部有ReadME.txt,简要说明

    C++日志库-线程安全

    线程安全的日志库在多线程环境下尤为重要,因为不正确的日志操作可能会导致数据竞争和同步问题。本文将详细讨论如何在C++中实现一个基于Win32接口的线程安全日志库,并关注其核心概念和技术。 首先,我们需要理解...

    高级程序员必会的HashMap的线程安全问题,适用于0~2年的.7z

    1. **使用线程安全的类**:Java提供了一些线程安全的Map实现,如`java.util.concurrent.ConcurrentHashMap`。ConcurrentHashMap使用分段锁技术,使得在保证线程安全的同时,提供了较好的并发性能。 2. **同步访问**...

    线程安全型栈

    实现线程安全型栈的主要目的在于解决多线程环境下的资源竞争问题。通过对栈的操作加上互斥机制,可以确保多个线程同时访问栈时不会出现错误。同时,线程安全型栈还能够提高多线程环境下的系统性能和可靠性。 为了...

    局部变量线程安全测试

    例如,如果局部变量引用了非线程安全的对象(如全局变量、静态变量或者共享资源),或者通过某种方式(如闭包)使得局部变量的生命周期超出了其定义的代码块,那么就可能出现线程安全问题。因此,即使变量本身是局部...

Global site tag (gtag.js) - Google Analytics