Era*_*dan 6 java functional-programming scala immutability thread-safety
我对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);
}
}
Run Code Online (Sandbox Code Playgroud)
可变,经典的线程安全版本:(或者我希望...)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有一种方法使用不可变对象和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;
}
}
Run Code Online (Sandbox Code Playgroud)
修改后的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);
}
}
Run Code Online (Sandbox Code Playgroud)
我有一种强烈的感觉,这也不是线程安全的,因为我从增量器读取,并且可能得到一个陈旧的值(例如,如果引用已经被另一个线程替换).如果它确实不是线程安全的,那么我想知道是否存在任何"功能"方式来处理这种没有锁定/同步的计数器场景.
所以我的问题是
虽然上面的示例代码是用Java编写的,但Scala中的回复当然也是受欢迎的
san*_*hat 13
这个线程是否安全?
不,除非您已在同步块中创建了不可变对象,否则这不是线程安全的.在线程竞争条件下有可能创建一个损坏的不可变对象.
要实现相同的功能,您可以使用AtomicInteger来避免显式同步.
public class Servlet extends HttpServlet {
public AtomicInteger incrementer = new AtomicInteger (0);
@Override
public void service(ServletRequest req, ServletResponse res) throws ... {
int newValue = incrementer.incrementAndGet();
super.service(req, res);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5576 次 |
| 最近记录: |