Is there a concurrency problem with java's run method - java

In my opinion, run method in Thread is invoked by jvm, is there a concurrency problem? when I read FutureTask's source code, I found it use CAS to set current thread. Why can't use:
runner = Thread.currentThread()
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
}
Also, why don't use if (state != NEW && !UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread())) so that run method can only be execute once,then set(result) can replace to
protected void set(V v) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
not
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
Is there necessary to use CAS?
when I use Future<Integer> futureTask1 = executor.submit(callable),submit method will RunnableFuture<T> ftask = newTaskFor(task). If I use
FutureTask futureTask = new FutureTask(new Callable() {
#Override
public Object call() throws Exception {
return null;
}
})
new Thread(futureTask);
new Thread(futureTask);
this is useless. So in diffrent threads there are diffrent RunnableFuture Object,therefore, there is no need for guarantee concurrent calls to run(), Could someone tell me what I miss,thanks
Developers who are new to the workplace are trying hard to learn multithreading knowledge, thank you for your answers

Related

JUnit run threads with static variable in Java

I'm trying to run two threads inside JUnit. The following code will be invoked by several JUnit test.
I want to stop both threads when result is not null. What should I do with it? The problem is multiple JUnit test share the same String result object and somehow this code gets blocked by previous test. The problem is when another test invoke this method, the result would assign to null, and previous test would block in while(true) loop.
static String result = null;
public static synchronized String remoteClogTailDir(final int maxRetry, String hostName,
final String identifier, final String remoteClogDirPaths, final String whichKeyValue) {
result = null;
final String[] hosts = hostName.split(",");
if(hosts != null && hosts.length == 2){
Thread t1 = null;
Thread t2 = null;
t1 = new Thread(new Runnable(){
#Override
public void run(){
String resultOfThread = null;
resultOfThread = remoteClogTailDir(maxRetry, hosts[0].trim(), identifier, null,
remoteClogDirPaths, false, whichKeyValue);
if(result == null && resultOfThread != null){
result = resultOfThread;
}
}
});
t2 = new Thread(new Runnable(){
#Override
public void run(){
String resultOfThread = null;
resultOfThread = remoteClogTailDir(maxRetry, hosts[1].trim(), identifier, null,
remoteClogDirPaths, false, whichKeyValue);
if(result == null && resultOfThread != null){
result = resultOfThread;
}
}
});
t1.start();
t2.start();
while(true){
if(result != null){
t1.interrupt();
t2.interrupt();
return result;
}
}
}else{
return remoteClogTailDir(maxRetry, hostName, identifier, null,
remoteClogDirPaths, false, whichKeyValue);
}
}
If I understand correctly, you want to execute several search in parallel, and take the first search which complete. You shouldn't use static properties for that.
You could use a ExecutorCompletionService for such tasks:
Executor executor = Executors.newCachedThreadPool();
CompletionService<String> ecs = new ExecutorCompletionService<String>(executor);
List<Future<String>> futures = new ArrayList<Future<String>>();
try {
futures.add(ecs.submit(search1));
futures.add(ecs.submit(search2));
for (int i = 0; i < futures.size(); ++i) {
String result = ecs.take().get();
if (result != null) {
return result;
}
}
} finally {
for (Future<String> f : futures) {
f.cancel(true);
}
}
executor.shutdownNow();
with search1 or search2 a simple Callable :
Callable<String> search1 = new Callable<String() {
public String call() {
return remoteClogTailDir(...)
}
}

FutureTask currency design

in java.util.concurrent.FutureTask#run
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
} }
what's mean of finally block comment ?
run() method cannot be concurrent called, because of the CAS .
why must wait the INTERRUPTING -> INTERRUPTED state transform finished ?
thank you !

Is there a read write lock with listeners for java?

Is there a java library that implements something that behaves like a ReadWriteLock but uses listeners or CompletableFuture/CompletionStage instead of blocking?
Ideally I'd like to write:
lock = ...
CompletionStage stage = lock.lockRead();
stage.thenAccept(r -> { doSomething(); r.release(); });
And also important:
CompletionStage stage = lock.tryLockWrite(10, TimeUnit.SECONDS);
stage.handle(callback);
I'm looking to know if something like this exists and if it does how is it called.
I'm not looking to implement this myself, but rather use a library to simplify some framework code.
I think writing it yourself shouldn't be hard enough. Chances are it would take less time than looking for a library. It's pretty simple overall:
static const int STATE_UNLOCKED = 0;
static const int STATE_READING = 1;
static const int STATE_WRITING = 2;
int state = STATE_UNLOCKED;
int readers = 0;
Queue<CompletableFuture<Void>> queueWriters = new LinkedList<CompletableFuture<Void>>();
Queue<CompletableFuture<Void>> queueReaders = new LinkedList<CompletableFuture<Void>>();
public synchronized CompletionStage<Void> lockWriter() {
CompletableFuture<Void> l = new CompletableFuture<Void>();
if (state == STATE_UNLOCKED) {
state = STATE_WRITING;
l.complete(null);
return l;
}
queueWriters.offer(l);
return l;
}
public synchronized CompletionStage<Void> lockReader() {
CompletableFuture<Void> l = new CompletableFuture<Void>();
if (state != STATE_WRITING) {
state = STATE_READING;
readers++;
l.complete(null);
return l;
}
queueReaders.offer(l);
return l;
}
public void unlock() {
CompletableFuture<Void> l = null;
synchronized(this) {
if (state == STATE_READING) {
readers--;
if (readers > 0) {
return;
}
}
l = queueReaders.poll();
if (l != null) {
state = STATE_READING;
readers++;
}
else {
l = queueWriters.poll();
if (l != null) {
state = STATE_WRITING;
}
else {
state = STATE_UNLOCKED;
return;
}
}
}
l.complete(null);
while (true) {
synchronized (this) {
if (state != STATE_READING) {
return;
}
l = queueReaders.poll();
if (l == null) {
return;
}
readers++;
}
l.complete(null);
}
}
Adding timed locking (By using some sort of "expiring queue" or writer-starvation prevention (By preventing additional readers from being executed if queueWriters is not empty) to the above shouldn't be that much more difficult either.

Adjacent synchronized blocks

I'm trying, for academic purpose, to implement something similar to Java high level locks, using the low level mechanism.
I want to implement a different semantics, in which the signaler thread has to wait until the signaled terminates its critical regional, but when the signaled terminates, the signaler has the precedence in order to get the lock.
My doubt is the following: in the attached code, the presence of two adjacent synchronized block is a problem?
I tried to solve the problem used the boolean modified in the synchronized sections, but because the sections locked on different things, I'm not sure about this solution.
public class FIFOLock {
private final Queue<QueueElement> entrySet;
private boolean busy;
private Thread owner;
protected Queue<Object> urgentQueue;
public FIFOLock() {
this.entrySet = new LinkedList();
this.urgentQueue = new LinkedList();
this.busy = false;
this.owner = null;
}
public void lock() throws InterruptedException {
QueueElement queued;
synchronized (this) {
if ((owner != null) && (owner.equals(Thread.currentThread())))
return; /* Lock already achieved */
if (!busy) {
busy = true;
this.owner = Thread.currentThread();
System.out.println("LockOwner: " + Thread.currentThread().getName());
// System.out.println("FREE");
return;
}
queued = new QueueElement(true);
entrySet.add(queued);
}
synchronized (queued) {
if (queued.isWaiting())
queued.wait();
this.owner = Thread.currentThread();
}
}
public void unlock() throws InterruptedException {
Object urgentElement = new Object();
QueueElement entryElement = new QueueElement(false);
boolean urgent = false;
synchronized (this) {
if (urgentQueue.size() != 0) {
urgentElement = urgentQueue.poll();
urgent = true;
} else {
if (entrySet.size() == 0) {
busy = false;
return;
}
entryElement = entrySet.poll();
}
}
if (urgent) {
synchronized (urgentElement) {
urgentElement.notify();
}
} else {
synchronized (entryElement) {
owner = null;
if (entryElement.isWaiting())
entryElement.notify();
entryElement.setWaiting(false);
}
}
}
}

Java - synchronous callback

I have the following code which is executed asynchronously. I would like to make it synchronous in order to follow some logical flow but I cannot work out how.
You will see that scanning is set to true to indicate that the method is still working, at the beginning - I then initiate a findPrinters(...) command - this contains a DiscoveryHandler which runs asynchronously - foundPrinter() is called each time an item is discovered. discoveryFinished() is when the discovery process is successfully completed, and discoveryError(...) is called whenever an error occurs.
I rely on something being set in my DiscoveryHandler before I would like to return from this method. Hence why I have while (scanning) underneath it. But this feels like a hack to me, and not the correct way of doing things. I cannot get wait() and notify() working. Can someone tell me what the correct way to do this is please?
private boolean findPrinter(final Context ctx) {
try {
scanning = true;
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
scanning = false;
}
public void discoveryError(String arg0) {
scanning = false;
}
});
} catch (Exception ex) {
}
while (scanning) {}
return false;
}
You could do this with CountDownLatch, which might be the lightest synchronization primitive in java.util.concurrent:
private boolean findPrinter(final Context ctx) {
final CountDownLatch latch = new CountDownLatch(1);
final boolean[] result = {false};
...
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
...
public void discoveryFinished() {
result[0] = true;
latch.countDown();
}
public void discoveryError(String arg0) {
result[0] = false;
latch.countDown();
}
...
}
// before final return
// wait for 10 seconds for the response
latch.await(10, TimeUnit.SECONDS);
//return the result, it will return false when there is timeout
return result[0];
}
There are a bunch of ways you can do this and wait()/notify() is probably not the best since you probably want to return something from your async method. As such I suggest using something like a BlockingQueue. Here is a simplified example of how you can do this:
private boolean findPrinter(final Context ctx) {
final BlockingQueue<?> asyncResult = new SynchronousQueue<?>();
try {
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
asyncResult.put(true);
}
public void discoveryError(String arg0) {
asyncResult.put(arg0);
}
});
} catch (Exception ex) {
}
Object result = asyncResult.take();
if (result instanceof Boolean) {
return (Boolean) result;
} else if (result instanceof String) {
logError((String) result);
}
return false;
}
One problem with using SynchronousQueue here though is that if discoveryFinished()/discoveryError() is called more than once, then the thread executing the code asynchronously will block forever since the SynchronousQueue assumes there will be exactly one take() per every put() and will block if a put() is made without a corresponding take() or vice versa. So if in your case those methods can be called more than once you would probably use a different kind of BlockingQueue instead (see documentation).

Categories