我只是一名非开发人员,可以成为开发人员,所以我的问题可能非常简单!
我只是测试Java多线程的东西,这不是真正的代码。我想知道如何在Java中同时更新两个成员变量,以防我们想要它们同步。举个例子:
public class Testing
{
private Map<String, Boolean> itemToStatus = new ConcurrentHashMap<>();
private Set<String> items = ConcurrentHashMap.newKeySet();
public static void main(String[] args)
{
(new Testing()).start("ABC");
}
public void start(String name) {
if (name.equals("ABC")) {
itemToStatus.put(name, true);
items.add(name);
}
}
}
在那种情况下(想象多线程,当然)我希望能够保证items
和itemToStatus
的任何读取始终返回相同的内容。
因此,如果代码在行itemToStatus.put(name, true)
中,而其他线程询问items.contains(name)
,则返回false。另一方面,如果其他线程询问itemToStatus.containsKey(name);
它将返回true。我不希望如此,如果有意义,我希望他们两者都给出相同的价值?
如何将这两个变化原子化?这会有用吗?
if (name.equals("ABC")) {
synchronised(this) {
itemToStatus.put(name, true);
items.add(name);
}
}
尽管如此,我不明白为什么会这样。我认为你需要一个锁或什么的情况?
干杯!
答案 0 :(得分:1)
只是同步写入不会起作用。您还需要同步(在同一对象上)对items
和itemToStatus
集合的读取访问权限。这样,如果另一个线程正在更新两个集合的过程中,没有线程可以读取任何内容。请注意,以这种方式同步意味着您不需要ConcurrentHashMap
或ConcurrentHashSet
;简单的旧HashMap
和HashSet
将起作用,因为您提供了自己的同步。
例如:
public void start(String name) {
if (name.equals("ABC")) {
synchronized (this) {
itemToStatus.put(name, true);
items.add(name);
}
}
}
public synchronized boolean containsItem(String name) {
return items.contains(name);
}
public synchronized boolean containsStatus(String name) {
return itemToStatus.containsKey(name);
}
这将保证containsItem
返回的值也会由containsStatus
返回,如果已经进行了此调用。当然,如果您希望返回值在一段时间内保持一致(如在第一次调用containsItem()
然后再调用containsStatus()
),则需要更高级别的同步。
答案 1 :(得分:0)
简短的回答是肯定的:通过同步代码块,就像在上一个代码片段中所做的那样,您使类成为线程安全的,因为该代码块是唯一一个读取或修改类状态的代码块(代表由两个实例变量)。
select <all-my-fields>, count(*)
from (
select <all-my-fields> from mytable
union all
select <all-the-fields> from mybackuptable
) merged_data
group by <all-my-fields>
having count(*) = 1
的含义是您使用对象的实例(select <all-my-fields>
from (
select max(source) source, <all-my-fields>, count(*)
from (
select 1 source, <all-my-fields> from mytable
union all
select 2, source, <all-the-fields> from mybackuptable
) merged_data
group by <all-my-fields>
having count(*) = 1
) minus_data
where source = 1
)作为锁:当线程进入该代码块时,它获得锁定,阻止其他线程进入相同的代码块,直到当线程从代码块退出时,它会释放它。