Java Thread-safe

本文通过一个计数器类的例子介绍了Java中线程安全的概念,并提供了两种实现线程安全的方法:使用synchronized关键字和AtomicInteger。同时,文章还列举了一些关于Java中线程安全的重要知识点。

http://javarevisited.blogspot.ca/2012/01/how-to-write-thread-safe-code-in-java.html

http://jcip.net.s3-website-us-east-1.amazonaws.com/listings.html

How to write Thread-Safe Code in Java

thread-safety or  thread-safe code in Java refers to code which can safely be used or shared in concurrent or multi-threading environment and they will behave as expected. any code, class or object which can behave differently from its contract on concurrent environment is not thread-safe. thread-safety is one of the risk introduced by using  threads in Java and I have seen java programmers and developers struggling to  write thread-safe code or just understanding  what is thread-safe code and what is not? This will not be very detailed article on thread-safety or low level details of  synchronization in Java instead we will keep it simple and  focus on one example of non thread-safe code and try to understand what is thread-safety and  how to make an code thread-safe.

How to make Thread-Safe Code in Java

Example of Non Thread Safe Code in Java

how to write thread-safe code in java example Here is an example of  non thread-safe code, look at the code and find out  why this code is not thread safe ?

/*
  * Non Thread-Safe Class in Java
 */
public class  Counter {
  
    private int count;
  
    /*
     * This method is not thread-safe because ++ is not an atomic operation
     */
    public int getCount(){
        return count++;
    }
}

Above example is not thread-safe because ++ (increment operator) is not an  atomic operation and can be broken down into read, update and write operation. if multiple thread call getCount() approximately same time each of these three operation may coincide or overlap with each other for example while thread 1 is updating value , thread 2 reads and still gets old value, which eventually let thread 2 override thread 1 increment and  one count is lost because multiple thread called it concurrently.

How to make code Thread-Safe in Java


There are multiple ways to make this code thread safe in Java:

1) Use  synchronized keyword in Java and lock the getCount() method so that only one thread can execute it at a time which removes possibility of coinciding or interleaving.

2) use  Atomic Integer, which makes this ++ operation atomic and since  atomic operations are thread-safe and saves cost of external synchronization.


here is a thread-safe version of Counter class in Java:



/*
 *  Thread-Safe Example in Java
 */
public class Counter {
  
    private int count;
    AtomicInteger atomicCount = new AtomicInteger( 0 );

  
    /*
     *  This method thread-safe now because of locking and synchornization
     */
    public synchronized int getCount(){
        return count++;
    }
  
    /*
     *  This method is thread-safe because count is incremented atomically
     */
    public int getCountAtomically(){
        return atomicCount.incrementAndGet();
    }
}


Important points about Thread-Safety in Java

Here is some points worth remembering to  write thread safe code in Java, these knowledge also helps you to avoid some serious concurrency issues in Java like race condition or  deadlock in Java:

1) Immutable objects are by default thread-safe because there state can not be modified once created. Since String is immutable in Java, its inherently thread-safe.
2) Read only or  final variables in Java are also thread-safe in Java.
3) Locking is one way of achieving thread-safety in Java.
4)  Static variables if not synchronized properly becomes major cause of thread-safety issues.

5) Example of thread-safe class in Java: Vector, Hashtable, ConcurrentHashMap, String etc.
6) Atomic operations in Java are thread-safe e.g. reading a 32 bit int from memory because its an atomic operation it can't interleave with other thread.
7) local variables are also thread-safe because each thread has there own copy and using local variables is good way to writing thread-safe code in Java.
8) In order to avoid thread-safety issue minimize sharing of objects between multiple thread.
9)  Volatile keyword in Java can also be used to instruct thread not to cache variables and read from main memory and can also instruct JVM not to reorder or optimize code from threading perspective.



That’s all on  how to write thread safe class or code in Java and avoid serious concurrency issues in Java. To be frank thread-safety is a little tricky concept to grasp, you need to think concurrently in order to catch whether a code is thread-safe or not. Also  JVM plays a spoiler since it can  reorder code for optimization, so the code which looks sequential and runs fine in development environment not guaranteed to run similarly in production environment because JVM may ergonomically adjust itself as server JVM and perform more optimization and reorder which cause  thread-safety issues.

Thanks


Read more:  http://javarevisited.blogspot.com/2012/01/how-to-write-thread-safe-code-in-java.html#ixzz2Q6tfnmYO

### 线程安全数据类型的替代方案 在 Java 和 C# 中,`volatile` 关键字用于确保变量的可见性,但它并不能提供原子操作或防止竞争条件的发生。因此,在某些情况下仅依赖 `volatile` 并不足以实现线程安全性。 #### 为什么仅使用 `volatile` 不足以保证线程安全? `volatile` 的主要作用是阻止指令重排序并确保多个线程能够看到共享变量的最新值[^1]。然而,它并不具备锁的功能,无法保护复合操作(例如读取和写入)。如果某个操作涉及多个步骤(比如先读取再更新),即使字段被声明为 `volatile`,仍然可能出现竞态条件。这是因为其他线程可能在这两个步骤之间介入执行,从而破坏一致性。 --- ### 正确的线程安全解决方案 以下是几种常见的线程安全数据类型及其适用场景: #### 1. **Atomic Classes** Java 提供了一组原子类来处理基本类型的无锁并发访问。这些类位于 `java.util.concurrent.atomic` 包下,包括但不限于: - `AtomicInteger` - `AtomicLong` - `AtomicReference` 它们通过硬件级别的 CAS(Compare-and-Swap)机制实现了高效的线程同步功能。例如,可以使用如下代码片段替换传统的加法运算以确保线程安全: ```java import java.util.concurrent.atomic.AtomicInteger; public class Counter { private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); // 原子操作 } public int getCount() { return count.get(); } } ``` C# 同样提供了类似的工具——`Interlocked` 类中的方法可用于完成类似的任务。例如: ```csharp using System; using System.Threading; class Program { static int counter = 0; static void Main(string[] args) { Interlocked.Increment(ref counter); // 使用 Interlocked 方法代替手动锁定 Console.WriteLine(counter); } } ``` --- #### 2. **Synchronized Blocks / Locks** 对于更复杂的逻辑,可以通过显式的锁机制来保障线程安全。在 Java 中,这通常意味着使用 `synchronized` 关键字;而在 C# 中,则推荐使用 `lock` 语句。 示例代码展示如何利用锁保护资源: ```java public class SharedResource { private final Object lock = new Object(); private int value; public void update(int newValue) { synchronized(lock) { // 锁定对象实例 value = newValue; // 更新状态 } } } ``` 对应的 C# 实现方式如下所示: ```csharp public class SharedResource { private readonly object _lock = new object(); private int _value; public void Update(int newValue) { lock (_lock) { // 加锁 _value = newValue; // 修改受保护的状态 } } } ``` 需要注意的是,虽然这种方法简单易懂,但在高并发环境下可能会引入性能瓶颈。 --- #### 3. **ThreadLocal Variables** 当希望每个线程拥有独立副本而不与其他线程共享时,可考虑采用 `ThreadLocal` 或其等价物。这种方式特别适合存储诸如数据库连接池之类的上下文敏感信息。 ```java private ThreadLocal<Integer> threadSpecificValue = ThreadLocal.withInitial(() -> 0); public void setThreadValue(int val) { threadSpecificValue.set(val); } public Integer getThreadValue() { return threadSpecificValue.get(); } ``` 尽管如此,过度依赖此类技术可能导致内存泄漏问题,尤其是在未清理不再使用的线程本地变量的情况下。 --- #### 4. **Immutable Data Structures** 不可变结构天然支持线程安全特性,因为一旦创建便不能再修改。任何变更都会返回一个新的实例而非改变原始对象。这种模式尤其适用于函数式编程风格的应用程序开发环境之中。 举例来说,下面展示了如何构建一个简单的只读集合: ```java import java.util.Collections; import java.util.List; List<String> immutableList = Collections.unmodifiableList(Arrays.asList("A", "B")); // 尝试向列表中添加元素会抛出 UnsupportedOperationException 异常 immutableList.add("C"); ``` 同样地,在 .NET Framework 下也有相应的 API 支持开发者定义不可变得容器类型。 --- ### 性能考量与优化建议 为了进一步提升应用程序的整体表现水平,应当依据实际需求权衡不同策略之间的利弊关系,并借助科学测量手段验证最终效果[^3]。例如,若频繁分配短生命周期缓冲区成为瓶颈所在,则有必要评估是否值得引入循环利用机制减少垃圾回收压力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值