|
|
|
/*
|
|
|
|
* Copyright (c) 2016-present, Facebook, Inc.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package codetoanalyze.java.checkers;
|
|
|
|
|
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
import javax.annotation.concurrent.ThreadSafe;
|
|
|
|
|
|
|
|
class C {
|
|
|
|
private int x = 0;
|
|
|
|
|
|
|
|
public int get() {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void set(int v) {
|
|
|
|
x = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@ThreadSafe
|
|
|
|
class ReadWriteRaces {
|
|
|
|
|
|
|
|
// read and write outside of sync races
|
|
|
|
Integer safe_read;
|
|
|
|
Integer racy;
|
|
|
|
|
|
|
|
void m0_OK(){
|
|
|
|
Integer local;
|
|
|
|
local = safe_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
void m0_OK2(){ //parallel reads are OK
|
|
|
|
Integer local;
|
|
|
|
local = safe_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
void m1(){ // A read where there are other writes
|
|
|
|
Integer local;
|
|
|
|
local = racy;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void m2(){
|
|
|
|
racy = 88;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void m3(){
|
|
|
|
racy = 99;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write inside sync, read outside of sync races
|
|
|
|
Object field1;
|
|
|
|
Object field2;
|
|
|
|
Object field3;
|
|
|
|
|
|
|
|
// need to report races involving safe writes in order to get this one
|
|
|
|
public synchronized void syncWrite1() {
|
|
|
|
field1 = new Object();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Object unprotectedRead1() {
|
|
|
|
return field1;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Object unprotectedReadInCallee() {
|
|
|
|
return field1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Object callUnprotecteReadInCallee() {
|
|
|
|
return unprotectedReadInCallee();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void syncWrite2() {
|
|
|
|
synchronized(this) {
|
|
|
|
field2 = new Object();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Object unprotectedRead2() {
|
|
|
|
return field2;
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized void syncWrite3() {
|
|
|
|
field3 = new Object();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void callSyncWrite3() {
|
|
|
|
syncWrite3();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Object unprotectedRead3() {
|
|
|
|
return field3;
|
|
|
|
}
|
|
|
|
|
|
|
|
private final C c = new C();
|
|
|
|
private final ReentrantLock lock = new ReentrantLock();
|
|
|
|
|
|
|
|
public void readInCalleeOutsideSyncBad(int i) {
|
|
|
|
if (c.get() > i) { // should report read/write race here
|
|
|
|
lock.lock();
|
|
|
|
c.set(i);
|
|
|
|
lock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|