私は Java が初めてで、Java の並行性を理解しようとしています。調べているうちに、Java の並行性に関する非常に人気のあるページで次のコードに出くわしました。
public class CrawledSites {
private List<String> crawledSites = new ArrayList<String>();
private List<String> linkedSites = new ArrayList<String>();
public void add(String site) {
synchronized (this) {
if (!crawledSites.contains(site)) {
linkedSites.add(site);
}
}
}
/**
* Get next site to crawl. Can return null (if nothing to crawl)
*/
public String next() {
if (linkedSites.size() == 0) {
return null;
}
synchronized (this) {
// Need to check again if size has changed
if (linkedSites.size() > 0) {
String s = linkedSites.get(0);
linkedSites.remove(0);
crawledSites.add(s);
return s;
}
return null;
}
}
}
ここでの関数 next() は、以下の行のように相互排除に違反していると思います。
if (linkedSites.size() == 0) {
return null;
}
同期ブロックの外に保持されるため、一部のスレッドが add() または next() で同期ブロック内のlinkedSitesを変更している場合、他のスレッドはそれを読み取ることができます.
間違っている場合は修正してください。