java 线程安全 计数_java – 实现线程安全共享计数器的功能方法

我对

Scala和函数式编程比较陌生,我喜欢使用不可变对象的想法,我可以避免许多线程安全陷阱.有一件事仍然困扰着我,这是用于教授线程安全的经典示例 – 共享计数器.

我想知道是否可以实现线程安全计数器(在此示例中为请求计数器),使用不可变对象和功能概念,并完全避免同步.

所以在这里参考首先是计数器的经典可变版本

(请原谅我的公共成员变量,仅为了简洁示例)

可变,非线程安全版本:

public class Servlet extends HttpServlet {

public int requestCount = 0;

@Override

public void service(ServletRequest req,ServletResponse res) throws ... {

requestCount++; //thread unsafe

super.service(req,res);

}

}

可变,经典的线程安全版本:(或者我希望…)

public class Servlet extends HttpServlet {

public volatile int requestCount = 0;

@Override

public void service(ServletRequest req,ServletResponse res) throws ... {

synchronized (this) {

requestCount++;

}

super.service(req,res);

}

}

我想知道是否有一种方法使用不可变对象和volatile变量来实现线程安全而不需要同步.

所以这是我天真的尝试.我们的想法是为计数器提供一个不可变对象,并使用volatile变量替换对它的引用.感觉很腥,但值得一试.

持有人:

public class Incrementer {

private final int value;

public Incrementer(final int oldValue) {

this.value = oldValue + 1;

}

public Incrementer() {

this.value = 0;

}

public int getValue() {

return value;

}

}

修改后的servlet:

public class Servlet extends HttpServlet {

public volatile Incrementer incrementer = new Incrementer();

@Override

public void service(ServletRequest req,ServletResponse res) throws ... {

incrementer = new Incrementer(incrementer.getValue());

super.service(req,res);

}

}

我有一种强烈的感觉,这也不是线程安全的,因为我从增量器读取,并且可能得到一个陈旧的值(例如,如果引用已经被另一个线程替换).如果它确实不是线程安全的,那么我想知道是否存在任何“功能”方式来处理这种没有锁定/同步的计数器场景.

所以我的问题是

>这个线程是否安全?

>如果是,为什么?

>如果没有,是否有任何方法可以在没有同步的情况下实现这样的计数器?

虽然上面的示例代码是用Java编写的,但Scala中的回复当然也是受欢迎的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值