• 欢迎访问天天编码网站,Java技术、技术书单、开发工具,欢迎加入天天编码
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏天天编码吧
  • 我们的淘宝店铺已经开张了哦,传送门:https://shop145764801.taobao.com/

如何创建一个线程安全的Java方法

Java高级 tiantian 1770次浏览 0个评论 扫描二维码

Java作为当今世界上使用人数最多的语言,在电脑硬件往多CPU多核发展的今天,Java也在慢慢地优化和增强多线程相关的特性。想成为一名合格,甚至优秀的Java工程师,必须熟练掌握Java多线程相关的知识。本文将从一个Google的Java面试题出发,详细讲述如何创建出一个线程安全的Java方法。

Google面试题

我们先来看一个网上流传的Google公司的Java面试题,读者可以测测自己的水平,是否已经可以去美帝搬砖了。

// Is the following method thread-safe? How to make it thread-safe?
// 下面的代码片段是线程安全的吗?如果不安全,如果改造成线程安全的?

class MyCounter {
private static int counter = 0;

public static int getCount() {
return counter++;
}
}

其实这个问题不仅是Google的面试题,我的前东家也使用了这个题目作为笔试题。这其实是一个Java线程相关的,比较简单和低层次的题目,完全没有涉及到如何设计高并发程序等高级问题。

首先,问题的答案是,该方法是线程不安全的。因为该方法的语句 counter++ 并不是一个原子操作,这个看似简单的操作的内部实际上不止有一个原子操作。实际上,counter++ 具有两个原子操作:一是访问counter值;而是counter值增加1。

如何创建一个线程安全的Java方法

我们可以简单分析一下多线程执行该方法时的情况:当线程 Thread1 中访问该方法时,线程 Thread2 可能还没有完全完成语句 counter++ 的执行,如果恰好停在两个原子操作之间时,Thread1 的访问该变量所获得的结果就是没有增加的值,可能不符合预期。

改造方法一

既然该方法不是线程安全的,那么如何改造该方法使之成为一个线程安全的方法呢?最简单地方式就是直接添加 同步(synchronized)关键词到该方法的声明语句上。当我们把 synchronized 添加到一个静态的方法声明上时,该方法使用的锁是该类的 Class 对象上的锁。

class MyCounter {
private static int counter = 0;

public static synchronized int getCount() {
return counter++;
}
}

可以看出来,把一个方法改造成线程安全的方法是非常简单的。需要注意的一点是:如果是把 synchronized 关键词添加到一个非静态的方法声明上,该方法使用的锁是该类的 示例对象(this对象) 上的锁。也就是说,一个类的静态方法和非静态方法分别使用了不同的两把锁,所有静态方法共用一把,所有非静态方法共用另一把。

改造方法二

了解过Java中同步机制的读者可能知道,除了同步方法,同步代码块的方式也可以很容易的实现改造方法一中的效果。由于同步方法和同步代码块非常相似,本文就不赘述了。此处提供的改造方法二是考虑到该方法的实现细节有一定的特殊性。在这个方法中,我们可以通过使用JDK中的原子类型 AtomicInteger 来代替普通的 int 类型,从而实现线程安全。

import java.util.concurrent.atomic.AtomicInteger;

public class MyCounter {
private static AtomicInteger counter = new AtomicInteger(0);

public static int getCount() {
return counter.getAndIncrement();
}
}

延伸扩展

局部变量都是线程安全的。这是有JVM中的内存布局模型决定的,每个线程都有自己私有的线程栈空间,而局部变量就是位于线程栈空间中。两个不同的线程不会共享相同的线程栈空间。所有方法中定义的局部变量都是分配在私有的线程栈空间中。一旦该方法对应的代码块执行完毕,其对应的线程栈空间也就被移除。


天天编码 , 版权所有丨本文标题:如何创建一个线程安全的Java方法
转载请保留页面地址:http://www.tiantianbianma.com/java-thread-safe-method.html/
喜欢 (6)
支付宝[多谢打赏]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址