线程的字符串字段上的 getter 和 setter 是否必须同步/
Should getter and setter on String field of a thread have to be synchronized/
我正在制作一个 Runnable,它会做一些独立的工作,但它的进度将由其他线程跟进。
为了做到这一点,我放置了一个私有字符串字段,其中包含我的线程的 "the state"。该线程将使用此字段的 setter 更新其进程,而其他线程将使用 getter 检索状态。
目前,我编写了以下代码并使用锁来同步我的 getter 和 setter。
但是不知道有没有必要
我想我的问题可以总结为:
"Does affectation are atomic in Java"
提前谢谢你,如果你花时间阅读我的问题。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FollowedThread implements Runnable {
private String state;
private final Lock lock;
public FollowedThread() {
lock = new ReentrantLock();
}
public void setState(String state) {
lock.lock();
try {
this.state = state;
} finally {
lock.unlock();
}
}
public String getState() {
String result;
lock.lock();
try {
result = state;
} finally {
lock.unlock();
}
return result;
}
@Override
public void run() {
setState("Step 1 running");
try {
Thread.sleep(1000);
setState("Step 2 running");
Thread.sleep(2000);
setState("Step 3 running");
Thread.sleep(3000);
setState("Thread finished");
} catch (InterruptedException e) {
setState("Thread interrupted");
}
}
}
没必要。没有任何东西会被破坏,因为这是一个原子操作。最坏的情况是您的 getter 将获得旧值。原子操作不需要锁。
现在最大的问题是 getter 获得绝对最新值有多重要?如果这与其他同步相关联,那么也许。将 volatile
关键字添加到 state
可能是避免数据变得太陈旧的好主意。
我想我找到了答案。
为了确保对字段的原子访问,您必须声明它 volatile。
有了它我的代码变成了:
package com.afklm.myactu.util;
public class FollowedThread implements Runnable {
private volatile String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
@Override
public void run() {
setState("Step 1 running");
try {
Thread.sleep(1000);
setState("Step 2 running");
Thread.sleep(2000);
setState("Step 3 running");
Thread.sleep(3000);
setState("Thread finished");
} catch (InterruptedException e) {
setState("Thread interrupted");
}
}
}
我正在制作一个 Runnable,它会做一些独立的工作,但它的进度将由其他线程跟进。
为了做到这一点,我放置了一个私有字符串字段,其中包含我的线程的 "the state"。该线程将使用此字段的 setter 更新其进程,而其他线程将使用 getter 检索状态。 目前,我编写了以下代码并使用锁来同步我的 getter 和 setter。 但是不知道有没有必要
我想我的问题可以总结为: "Does affectation are atomic in Java"
提前谢谢你,如果你花时间阅读我的问题。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FollowedThread implements Runnable {
private String state;
private final Lock lock;
public FollowedThread() {
lock = new ReentrantLock();
}
public void setState(String state) {
lock.lock();
try {
this.state = state;
} finally {
lock.unlock();
}
}
public String getState() {
String result;
lock.lock();
try {
result = state;
} finally {
lock.unlock();
}
return result;
}
@Override
public void run() {
setState("Step 1 running");
try {
Thread.sleep(1000);
setState("Step 2 running");
Thread.sleep(2000);
setState("Step 3 running");
Thread.sleep(3000);
setState("Thread finished");
} catch (InterruptedException e) {
setState("Thread interrupted");
}
}
}
没必要。没有任何东西会被破坏,因为这是一个原子操作。最坏的情况是您的 getter 将获得旧值。原子操作不需要锁。
现在最大的问题是 getter 获得绝对最新值有多重要?如果这与其他同步相关联,那么也许。将 volatile
关键字添加到 state
可能是避免数据变得太陈旧的好主意。
我想我找到了答案。 为了确保对字段的原子访问,您必须声明它 volatile。 有了它我的代码变成了:
package com.afklm.myactu.util;
public class FollowedThread implements Runnable {
private volatile String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
@Override
public void run() {
setState("Step 1 running");
try {
Thread.sleep(1000);
setState("Step 2 running");
Thread.sleep(2000);
setState("Step 3 running");
Thread.sleep(3000);
setState("Thread finished");
} catch (InterruptedException e) {
setState("Thread interrupted");
}
}
}