I'm trying to synchronize a String literal, so that I can control the execution of my threads but for some reason that does not work..
Is there any problem with the way its synchronized?
package scratch1;
public class OrderedThread {
public static void main(String[] args){
RunThread first, second, third;
OrderedThread orderedthread = new OrderedThread();
first = new RunThread("One",orderedthread);
second = new RunThread("Two",orderedthread);
third = new RunThread("Three",orderedthread);
second.start();
first.start();
third.start();
}
public void display(String msg){
synchronized(msg){
for (int i = 1; i <= 20; i++){
System.out.println("Name = "+ msg);
}
}
}
}
class RunThread extends Thread{
String name;
OrderedThread orderT;
RunThread(String name, OrderedThread orderT){
this.name = name;
this.orderT = orderT;
}
public void run(){
orderT.display(name);
}
}
The point of synchronization is access to shared resources. Your thread is supposed to acquire the monitor on an object that other threads are trying to access. In your case, each thread acquires a different object's monitor, so none of them blocks.
If instead you passed the literal "One" to your constructors
first = new RunThread("One",orderedthread);
second = new RunThread("One",orderedthread);
third = new RunThread("One",orderedthread);
Then you would see execution in order. Each thread would have to finish its for-loop (inside the synchronized block) before another one can start. This is because each Thread is synchronized on the same String object.
Better yet, use one of them many java.util.concurrent classes that act as locks. For example, Lock.
Related
public class Test implements Runnable{
private String name;
public Test(String name){
this.name = name;
}
public void run() {
blah(name);
}
public synchronized void blah(String obj) {
System.out.println("Here: "+obj);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Test x = new Test("X");
Test y = new Test("Y");
Thread tx = new Thread(x);
Thread ty = new Thread(y);
tx.start();
ty.start();
}
This example should help me to understand synchronization, but I don't. This is because if I remove the word synchronize, it printed the same output (random)
Synchronization is irrelevant here because your two threads are each synchronizing on their own Runnable. There is no shared lock, and no shared data.
If you pass the same Runnable instance into each Thread then they will share the same lock. If your Runnable does something in a thread-unsafe way (like using ++ to increment a shared variable (an instance variable of the Runnable), or adding the entry to a shared ArrayList) then you can create a situation where removing synchronization can make the code break (with the understanding that breakage may not happen reliably, that's what makes multithreaded programming fun).
Making toy examples like this is not a good preparation for real-life multithreading. Threads shouldn't be in the business of implementing locking, they should be accessing data objects that enforce their own invariants.
Your example is technically correct, but there is no timing dependent conflict in your synchronized block. As such, there is no chance that you will see different output, regardless of the ordering of the calls.
In addition, you create two resources, and there is no cross-thread communication between the two resources, so effectively you've tested two synchronized blocks once each.
You need an example that can break when not synchronized.
Here is an example that can break
public class Counter {
int count;
public Counter() {
count = 0;
}
public int getCount() {
return count;
}
public /* need synchronized here */ void update(int value) {
int buffer = 0;
buffer = buffer + count;
buffer = buffer + value;
count = buffer;
}
}
public class UpdateCounter extends Thread {
public UpdateCounter(Counter counter, int amount) {
this.counter = counter;
this.name = name;
}
public void run() {
System.out.printf("Adding %d to count\n", amount);
counter.update(amount);
System.out.printf("Count is %d\n", counter.getCount());
}
}
public static void main(String[] args) {
Counter counter = new Counter();
UpdateCounter x = new UpdateCounter(counter, 30);
UpdateCounter y = new UpdateCounter(counter, 100);
x.start();
y.start();
}
With an example like this, one would eventually see a series of lines that indicated some value was being added to the counter, but the counter would update by the wrong value.
This is because one thread will eventually get paused with a buffer holding the "next" value, and the other thread will race across the same block of code, storing its "next" value into count. Then the paused thread will un-pause, and store its "next" value effectively removing the amount added by the thread that raced ahead of it.
By adding the synchronized keyword, only one thread is allowed entry into the update block, and the race condition I described above cannot occur.
Note that this is an example that can fail with bad synchronization, and not a good way to implement a counter.
The following code sometimes prints "valueWrapper.isZero()" on my Windows-PC and a Mac,
both running their JVM in server mode.
Ok this happens because the value field isn't final in the ValueWrapper class,
so its possible that some thread sees the stale value 0.
public class ConcurrencyApp {
private final Random rand = new Random(System.currentTimeMillis());
private ValueWrapper valueWrapper;
private static class ValueWrapper {
private int value;
public ValueWrapper(int value) {
this.value = value;
}
public boolean isZero() {
return value == 0;
}
}
private void go() {
while (true) {
valueWrapper = new ValueWrapper(randomInt(10, 1024));
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
if (valueWrapper.isZero()) {
System.out.println("valueWrapper.isZero()");
}
}
});
thread.start();
}
}
private int randomInt(int min, int max) {
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public static void printVMInfos() {
String vmName = System.getProperty("java.vm.name");
System.out.println("vm name: " + vmName);
int cores = Runtime.getRuntime().availableProcessors();
System.out.println("available cores: " + cores);
}
public static void main(String[] args) {
ConcurrencyApp app = new ConcurrencyApp();
printVMInfos();
app.go();
}
}
But what about the following modification, here i used a local final variable:
private void go() {
while (true) {
final ValueWrapper valueWrapper = new ValueWrapper(randomInt(10, 1024));
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
if (valueWrapper.isZero()) {
System.out.println("valueWrapper.isZero()");
}
}
});
thread.start();
}
}
It looks like that now no thread sees a stale value of 0.
But is this guaranteed by the JMM?
A brief look in the spec doesn't convinced me.
It looks like that now no thread sees a stale value of 0. But is this guaranteed by the JMM? A brief look in the spec doesn't convinced me.
It is guaranteed but not because of the final. There is a happens-before guarantee when you fork a thread. Any memory operations done in the forking thread before you start a new thread are guaranteed to be seen by the new thread as fully constructed and published. To quote from JLS 17.4.4 - Synchronization Order:
An action that starts a thread synchronizes-with the first action in the thread it starts.
This is different from a final field when we are talking about object construction and publishing. If a field is final then it is guaranteed to be properly initialized when the constructor finishes and the object is published to multiple threads. In your case, the final is necessary because of the anonymous class. If you weren't using an anonymous class and then you could remove the final on your ValueWrapper, your object would still be guaranteed to be fully constructed because of the above.
FYI, see here for final field info: Java concurrency: is final field (initialized in constructor) thread-safe?
I am addressing one point Gray didn't, but I would accept his, as his answer is spot on
The following code sometimes prints "valueWrapper.isZero()" on my Windows-PC and a Mac, both running their JVM in server mode.... It looks like that now no thread sees a stale value of 0. But is this
guaranteed by the JMM? A brief look in the spec doesn't convinced me.
The reason you are seeing valueWrapper.isZero() returning true sometimes because valueWrapper is changing after the start is invoked and before run gets to the boolean test. If you only have one instance created it will always not be zero as Gray mentioned.
The reason final ValueWrapper valueWrapper = new ValueWrapper(randomInt(10, 1024)); works all the time is because the field is thread (and method) local and the semantics for a local object and anonymous inner classes is to copy the original reference into the class instance.
I am currently learning basics of Threads in Java and I am trying to write a program simulating a 2x200 Relay race with 2 teams. I would like to have 2 teams (represented by a ThreadGroup each) and each team has 2 members, each of which must run for 200 m. Here running is just simulated by looping in a for loop and printing. I am not able to find a straight forward way of running threads in a Threadgroup in serially
Here is how the worker looks like
public class RelayRunner implements Runnable {
#Override
public void run() {
for (int i = 1; i <= 200; i++) {
String name = Thread.currentThread().getName();
if (i % 50 == 0) {
System.out.format("%s ran %d m \n", name, i);
}
}
}
}
Here is how the main program looks like
public class RelayRunnerMatch {
public static void main(String[] args) {
RelayRunner relayRunner = new RelayRunner();
ThreadGroup usa = new ThreadGroup("USA");
ThreadGroup germany = new ThreadGroup("GERMANY");
Thread usa1 = new Thread(usa, relayRunner, "usa1");
Thread germany1 = new Thread(germany, relayRunner, "germany1");
Thread usa2 = new Thread(usa, relayRunner, "usa2");
Thread germany2 = new Thread(germany, relayRunner, "germany2");
usa1.start();
germany1.start();
/* Now I would like to start the second thread in a group only if the first
thread in the same group has finished like in a real relay race. How??
*/
//usa1.join(); germany1.join();
//usa2.start(); germany2.start() --> Not good, usa2 must start immediately when usa1 has finished
}
}
I am not able to see how the join() may be of any help here as it will wait for both threads to finish before the second set of runners can start their run. Also I realize that activeCount() is just an estimate, so I am not sure of using that either.
Is there a solution possible without resorting to services in new Concurrent API(as I haven't reached that further)?
public class Player1 implements Runnable{
private final CountDownLatch countDownLatch;
private final String s;
public Player1(CountDownLatch c, String s){
this.countDownLatch=c;
this.s=s;
}
#Override
public void run() {
for(int i=0;i<200;i++){
System.out.println(s+":"+i);
}
countDownLatch.countDown();
}
}
public class Player2 implements Runnable{
private final CountDownLatch countDownLatch;
private final String s;
public Player2(CountDownLatch c, String s){
this.countDownLatch = c;
this.s=s;
}
#Override
public void run() {
try {
countDownLatch.await();
} catch (InterruptedException ex) {
Logger.getLogger(Player2.class.getName()).log(Level.SEVERE, null, ex);
}
for(int i=0;i<200;i++){
System.out.println(s+":"+i);
}
}
}
Driver program:
public static void main(String[] args){
Thread[] grp1 = new Thread[2];
Thread[] grp2 = new Thread[2];
CountDownLatch c1 = new CountDownLatch(1);
CountDownLatch c2 = new CountDownLatch(1);
grp1[0]=new Thread(new Player1(c1, "grp1:player1"));
grp1[1]=new Thread(new Player2(c2, "grp1:player2"));
grp2[0]=new Thread(new Player1(c2, "grp2:player1"));
grp2[1]=new Thread(new Player2(c2, "grp2:player2"));
grp1[0].start();
grp2[0].start();
grp1[1].start();
grp2[1].start();
}
You could create two baton-objects and synchronize on the respective baton so the second thread would have to wait until the first one releases the baton - or use some locks from java.util.concurrent.locks-package to achieve the same. But your relay-members will compete in who gets the baton first or next and you can't define some real order.
But as Jarrod said: when you have several tasks that have to be executed sequentially you better execute them on the same thread: have some runner-objects and add them to a queue on the respective relay-thread that calls their run-method one after the other.
I'm trying to access and modify a variable of a thread in another thread in java, and I really don't know how to do this.
ex :
Runnable r1 = new Runnable() {
int value = 10;
public void run() {
// random stuff
}
}
Runnable r2 = new Runnable() {
public void run() {
// of course the bellow line will not work
r1.value--; // I want here to be able to decrement the variable "value" of r1
}
}
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
Is there any way to create a getter and setter for a thread in java?
Edit: the answers were good, but I was not clear in my question, I will try asking a better question
You could make it sort of work but, I suggest you use an AtomicInteger which is shared between threads.
final AtomicInteger value = new AtomicInteger(10);
Runnable r1 = new Runnable() {
public void run() {
// random stuff using value
}
}
Runnable r2 = new Runnable() {
public void run() {
value.decrementAndGet();
}
}
You can use AtomicReference for references to objects.
Create a runnable, and use the setters and getters you define in said runnable.
public class MyRunnable implements Runnable{
private volatile String myString;
public String setString(String value){this.myString = value;}
public String getString(){
return myString;
}
public void run(){}
}
Note volatile keyword is used here. The volatile keyword ensures if this String changes in one thread, that all threads will see the change. If instead I ensure that the only access to the String object is through synchronized context, then the volatile keyword would not be necessary.
To demonstrate my point, the above code and the below code are both thread-safe but are different as no 2 threads can enter setString and getString simultaneously in the example below.
public class MyRunnable implements Runnable{
private String myString;
public synchronized String setString(String value){this.myString = value;}
public synchronized String getString(){
return myString;
}
public void run(){}
}
A thread is really just executing a runnable. You could use this like so:
MyRunnable runnable = new MyRunnable();
Thread myThread = new Thread(runnable);
myThread.start();
String myString = runnable.getString();
Using atomic values for primitives is fine, but if you ever want to share a more complex object, you'll have to read about threading and synchronization.
For example:
public class Stats{
int iterations;
long runtime;
public Stats(){
iterations = 0;
runtime=0;
}
public synchronized void setIterations(int value){this.iterations = value;}
public synchronized void setRuntime(long milliseconds){
this.runtime = milliseconds;
}
public synchronized int getIterations(){
return iterations;
}
public synchronized long getRuntime(){return runtime;}
}
public class StatRunnable implements Runnable{
Stats stats;
boolean active;
public StatRunnable(){
this.active=true;
}
public Stats getStats(){
return stats;
}
long calculateRuntime(){return 0L;}
public void run(){
while(active){
//i'm synchronizing with stats to ensure no other thread alters values
//simultaneously.
synchronized(stats){
stats.setIterations(stats.getIterations()+1);
stats.setRuntime(calculateRuntime());
}
}
}
}
This code shows an example of synchronization with non-primitive objects via the synchronized keyword. Using the synchronized keyword in a method definition locks the class using itself as the synchronizing object.
A final note, the synchronized keyword isn't just used in method definitions. You can use it to synchronize on instances within methods as I've done in the run method in StatRunnable.
Given this code:
public class Messager implements Runnable {
public static void main(String[] args) {
new Thread(new Messager("Wallace")).start();
new Thread(new Messager("Gromit")).start();
}
private String name;
public Messager(String name) { this.name = name; }
public void run() {
message(1); message(2);
}
private synchronized void message(int n) {
System.out.print(name + "-" + n + " ");
}
}
I understand that the synchronized keyword makes the thread dependent on the object's lock. Questions:
a) Is the lock released as soon as the method marked as synchronized finishes? Or as soon as the thread's run() method finishes
b) Can I ensure that any one of the threads will print its name and 1 2 before the other?
A. Yes. It's released as soon as the synchronized function finishes.
B. Yes. You can, but if you wanted to do so, why would you write multithreaded code in the first place? synchronized guarantees atomicity, not anything regarding the order, but you can enforce order by waiting for a flag to change. Anyway, what you are trying to enforce is sequentiality. You get this for free in single-threaded environments :)