class ABC implements Runnable {
private static int a;
private static int b;
public void run() {
}
}
我有一个如上所示的Java类。我有多个此类的线程。在run()
方法中,变量a
和b
分别被多次递增。在每次递增时,我都会将这些变量放入Hashtable中。
因此,每个线程都会递增这两个变量并将它们放入Hashtable中。我该如何使这些操作线程安全?
class ABC implements Runnable {
private static int a;
private static int b;
public void run() {
}
}
我有一个如上所示的Java类。我有多个此类的线程。在run()
方法中,变量a
和b
分别被多次递增。在每次递增时,我都会将这些变量放入Hashtable中。
因此,每个线程都会递增这两个变量并将它们放入Hashtable中。我该如何使这些操作线程安全?
我会使用AtomicInteger,它被设计为线程安全的,易于使用,并且对应用程序带来绝对最少的同步开销:
class ABC implements Runnable {
private static AtomicInteger a;
private static AtomicInteger b;
public void run() {
// effectively a++, but no need for explicit synchronization!
a.incrementAndGet();
}
}
// In some other thread:
int i = ABC.a.intValue(); // thread-safe without explicit synchronization
取决于需要保证线程安全的内容。对于这些int
原始类型,您需要将它们替换为AtomicInteger
或仅在synchronized
方法或块中操作。如果您需要使跨线程的Hashtable线程安全,则无需执行任何操作,因为它已经是同步的。
volatile
的理解有误。已经更正了答案。 - Alex Abdugafarovfinal int
将是线程安全的,因为它是不可变的 - 仅仅将可变对象(例如ArrayList
)设置为final
并不能神奇地使其线程安全。即使将其getter同步也没有帮助。您必须代理和同步所有实例希望公共方法,而不提供对实例本身的访问。 - Alex Abdugafarovsynchronized
方法。public synchronized void increment()
{
a++; b++;
// push in to hash table.
}
如果您只通过单个实例访问静态内容,则上述方法很好,但是如果您有多个实例,则需要对某些静态对象进行同步 - 类似于以下内容(未经测试)...
private static Object lock = new Object();
public void increment()
{
synchronize(lock)
{
a++;b++;
// do stuff
}
}
a
和b
的值,其他答案强调了如何使用原子操作单独增加它们的值。synchronize(ABC.class) { ... }
- mcfinnigan
public void run() { synchronized(SharedCounter.class) { SharedCounter.count++; } }
然而,这段代码效率低下,因为它每次都要获取和释放锁来增加计数器的值。 - shareef