`
san_yun
  • 浏览: 2638448 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

这段代码线程安全吗?

 
阅读更多

从一篇博客上看到的,问下面的代码是否是线程安全的

public class Cache {
       private Map cache = new HashMap() ; 
       public Object get(String key) {
          return cache.get(key);
       }
 
       public void reload(){
          Map tempCache = loadFromDB();
          cache = tempCache; // safe ?
       }
}

 

我的答案是是线程安全的,原因可以参考CopyOnWriteArrayList的做法。

1、JAVA中“=”操作只是将引用和某个对象关联,假如有一个线程将引用指向另外一个对象,同时另一线程获取这个引用指向的对象,那么他们之间不会发生ConcurrentModificationException,他们是在虚拟机层面阻塞的,而且速度非常快,几乎不需要CPU时间。

2、JAVA中两个不同的引用指向同一个对象,当第一个引用指向另外一个对象时,第二个引用还将保持原来的对象。

在CopyOnWriteArrayList里处理写操作(包括add、remove、set等)是先将原始的数据通过JDK1.6的Arrays.copyof()来生成一份新的数组

然后在新的数据对象上进行写,写完后再将原来的引用指向到当前这个数据对象(这里应用了常识1),这样保证了每次写都是在新的对象上(因为要保证写的一致性,这里要对各种写操作要加一把锁,JDK1.6在这里用了重入锁),

然后读的时候就是在引用的当前对象上进行读(包括get,iterator等),不存在加锁和阻塞,针对iterator使用了一个叫 COWIterator的阉割版迭代器,因为不支持写操作,当获取CopyOnWriteArrayList的迭代器时,是将迭代器里的数据引用指向当前 引用指向的数据对象,无论未来发生什么写操作,都不会再更改迭代器里的数据对象引用,所以迭代器也很安全(这里应用了常识2)。

CopyOnWriteArrayList中写操作需要大面积复制数组,所以性能肯定很差,但是读操作因为操作的对象和写操作不是同一个对象,读之 间也不需要加锁,读和写之间的同步处理只是在写完后通过一个简单的“=”将引用指向新的数组对象上来,这个几乎不需要时间,这样读操作就很快很安全,适合 在多线程里使用,绝对不会发生ConcurrentModificationException ,所以最后得出结论:CopyOnWriteArrayList适合使用在读操作远远大于写操作的场景里,比如缓存。

分享到:
评论

相关推荐

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

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

    day33线程安全代码块设计思路_线程代码安全块_源码

    在Java中,如果一个方法或代码块被`synchronized`修饰,那么它将被视为线程安全的,因为只有一个线程能执行这段代码,其他试图访问的线程必须等待。 线程安全代码块,也称为同步代码块,语法结构如下: ```java ...

    C#进程线程安全的LOG帮助,支持输出当前错误行数错误文件

    为了确保线程安全,这个LOG帮助类会使用C#提供的锁(lock)机制或者其他并发控制结构,如Monitor、Mutex或Semaphore,来保护对共享日志文件的访问。这样,即使在高并发情况下,日志记录也能保持正确性和完整性。 ...

    如何实现多线程多任务?

    在计算机编程中,多线程和多任务是提高...在实际开发中,还需要考虑线程安全、错误处理、调试等问题,确保程序的稳定性和可靠性。通过不断实践和学习,你将能更好地掌握多线程编程技巧,充分利用现代计算机的多核优势。

    C# 高效线程安全,解决多线程写txt日志类

    线程安全意味着当多个线程访问同一段代码时,该代码能正确处理并发操作,不会出现数据不一致或竞态条件等问题。在多线程写入txt日志时,如果没有正确的同步机制,可能会导致日志条目混合、丢失或者错误的顺序。 ...

    线程安全Vector

    它指的是一个类或一段代码能够被多个线程同时调用而不会导致数据不一致或其他错误的情况。线程安全性确保了在多线程环境下代码的正确执行。 ##### 定义与理解 定义线程安全性往往较为复杂,常见的定义通常涉及代码...

    线程通信安全问题

    synchronized可以用于方法或代码块,确保同一时间只有一个线程可以执行特定的代码段,防止数据不一致。然而,有时我们需要更精细的控制,比如让一个线程等待另一个线程完成某些操作后再继续执行,这时就需要用到线程...

    多线程开发及其源代码

    总之,多线程开发是一项复杂而实用的技能,通过学习"多线程开发及其源代码",你可以更好地理解和掌握这一技术,为你的编程生涯增添新的武器。实践是检验真理的唯一标准,所以一定要动手尝试,从实践中积累经验。

    NET:一段比较经典的多线程学习代码

    这段代码是.NET环境中一个关于多线程编程的经典示例,主要展示了如何使用Mutex进行线程同步以及处理线程的顺序问题。Mutex是一个临界区对象,用于控制对共享资源的并发访问,确保同一时间只有一个线程能执行特定的...

    远程线程注入asm代码

    3. **分配内存**:使用`VirtualAllocEx`函数在目标进程中分配内存,这段内存将用来存放我们的ASM代码和任何必要的数据。 4. **写入内存**:使用`WriteProcessMemory`函数将ASM代码写入目标进程的内存空间。 5. **...

    Java 线程通信示例 源代码

    通过分析和理解这些示例,开发者可以更好地掌握如何在实际项目中实现线程安全的代码,提高程序的性能和稳定性。多线程通信是并发编程的基石,理解并熟练运用这些技术对于任何Java开发人员来说都是必不可少的。

    Winform基于多线程实现每隔1分钟执行一段代码

    6. **线程安全**:虽然这个简单的定时器实现没有特别处理线程同步问题,但在`Stop`方法中尝试停止线程时,它调用了`Abort`方法,这是一个粗暴的停止方式,可能会导致未完成操作的问题。在实际开发中,推荐使用更优雅...

    远程注入线程实例代码

    本实例代码“远程注入线程实例代码”聚焦于如何将一段代码注入到一个远程进程中并创建一个新的线程来执行这段代码。下面将详细阐述这一技术的核心概念和实现步骤。 线程注入的概念: 线程注入是程序设计中的一个...

    C++学习 线程创建代码

    这段代码是一个典型的使用Windows API来创建线程的例子,尤其适合C++初学者作为学习线程编程的基础。 ### 线程简介 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个...

    多线程代码9.rar多线程代码9.rar多线程代码9.rar

    5. **线程安全**:如果一段代码可以在多线程环境中正确运行,不会因线程间的交互导致错误,那么它被称为线程安全。 6. **死锁**:当两个或更多线程互相等待对方释放资源而无法继续执行时,就会发生死锁。 7. **...

    CVI 04.多线程数据保护(安全变量

    它们被设计为线程安全的,即在并发访问时,这些变量的修改不会导致不一致的结果。常见的安全变量包括互斥量(Mutex)、信号量(Semaphore)、条件变量(Condition Variable)以及原子操作(Atomic Operations)。 1...

    c语言 日志分级 线程安全 slog.rar

    本文将详细讲解"c语言 日志分级 线程安全 slog"这一主题,以及如何利用名为`slog`的C语言实现的日志模块。 首先,让我们了解日志分级的概念。日志分级是一种管理日志输出的方法,它允许开发者根据信息的重要性和...

    gethostbyname_r在某些linux版本中多线程不安全问题.pdf

    这段代码存在竞态条件,可能会导致线程不安全的问题。 解决方案: 为了解决这个问题,可以使用预防的方法,例如使用线程锁来保护共享资源,或者使用其他 DNS 解析函数来替代 gethostbyname_r 函数。 在 Linux ...

    vb多线程演示代码

    通过学习和实践这个“vb多线程演示代码”,开发者可以掌握如何在VB中高效地利用多线程,提升程序的并发性能,同时理解如何避免可能出现的线程安全问题。这个压缩包对于初学者和经验丰富的开发者都是宝贵的资源,能够...

Global site tag (gtag.js) - Google Analytics