Synchronized method in java does not work as indended - java

I want to learn how to use the synchronized method in java and implemented the following code.
public class checkThread {
volatile int i = 0;
public void increment() {
i++;
}
}
public class TestSync extends checkThread{
public static void main(String[] args) {
checkThread ct1 = new checkThread();
Object iLock = new Object();
for(int i = 0 ; i < 10 ; i++) {
extracted(ct1, iLock);
}
}
private static void extracted(checkThread ct1, Object iLock) {
synchronized (iLock) {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t1.start();
}
synchronized (iLock) {
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t2.start();
}
synchronized (iLock) {
System.out.println(ct1.i);
}
}
}
However the output I get is not at all synchronized!
1000
2000
4000
6000
8000
9000
11575
13575
15575
17459
Why am I getting such an output and not the desired value of i in the multiples of 1000?

If you are trying to make sure that the run() method will be completed by one thread before the other one start; then you need to synchronize the content inside the run method, not the thread creation part.
In your specific example, you need to have an object that can be accessed by both the threads, and then acquire the lock of that object.
Let me add an example below by changing your code; but this may not be the best way; just trying to explain the point.
checkThread iLock = new checkThread();
public void someMethod() {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (iLock) {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t1.start();
}
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (iLock) {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t2.start();
}
synchronized (iLock) {
System.out.println(ct1.i);
}
}

Related

How do I run 2 Threads alternately

I am new to Threading and I'm trying to make Output look like: aAbBcCdDeE... .
I searched and tried a lot of stuff but nothing really made it work. In the Exercise you are supposed to do it with a global boolean variable but I didn't really find anything useful and am kinda lost. I appreciate the help!
public class ABCThread implements Runnable {
char c;
public ABCThread(char c) {
this.c = c;
}
#Override
public synchronized void run() {
for (char i = 0; i < 26; i++) {
System.out.println(c++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ABCThread('a'));
Thread t2 = new Thread(new ABCThread('A'));
t1.start();
t2.start();
}
}
Output:
a
A
B
b
C
c
d
D
e
E
f
F
G
g
H
h
I
i
J
j
Here is the one of the solution to solve the given problem. It uses wait to wait the current thread after printing one letter and notify the other thread to print its letter, and same cycle repeats. The concept of Thread wait and notify is very well explained here.
Short description:
To wait or notify any thread, it (invoking thread) must acquire the lock on any common object. In below example, each thread is acquiring the lock on this (self) (via synchronized run method) to wait and on opponent to notify it (the another thread).
public class App implements Runnable {
char c;
App opponent;
boolean go;
public App(char c, boolean go) {
this.c = c;
this.go = go;
}
public void setOpponent(App opponent) {
this.opponent = opponent;
}
public static void main(String[] args) {
App a = new App('a', true);
App b = new App('A', false);
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
a.setOpponent(b);
b.setOpponent(a);
t1.start();
t2.start();
}
#Override
public synchronized void run() {
for (char i = 0; i < 26; i++) {
try {
if (go) {
System.out.println(c++);
this.wait();
synchronized (opponent) {
opponent.notify();
}
} else {
System.out.println(c++);
synchronized (opponent) {
opponent.notify();
}
this.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Here is the more simplified and understandable version of above code. In this code, both the threads are acquiring lock on same lock object, printing the letter, going in WAIT state (so release the lock) and giving turn to other BLOCKED thread waiting for the lock on lock. The other thread then acquires the lock on lock, prints the letter, notifies the previous thread which was waiting on lock object, and goes into WAIT condition, thus releasing the lock.
public class App2 implements Runnable {
char c;
Object lock;
boolean go;
public App2(char c, boolean go) {
this.c = c;
this.go = go;
}
public void setLock(Object lock) {
this.lock = lock;
}
public static void main(String[] args) {
App2 a = new App2('a', true);
App2 b = new App2('A', false);
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
Object lock = new Object();
a.setLock(lock);
b.setLock(lock);
t1.start();
t2.start();
}
#Override
public void run() {
for (char i = 0; i < 26; i++) {
synchronized (lock) {
try {
if (go) {
System.out.println(c++);
lock.wait();
lock.notify();
} else {
System.out.println(c++);
lock.notify();
lock.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
UPDATE:
Above two approaches will work in most of the cases, but will not guarantee that t1 will be executed before t2 every time. Though t1 is started before t2, but it does not mean that thread scheduler will always pick t1 to execute before t2. To be sure that t1 will execute before t2 in every case, we need to ensure that t2 gets started once t1 is in RUNNABLE state (i.e. running). Below is the one of the way of how we can achieve it:
public class App3 implements Runnable {
char c;
App3 opponent;
boolean go;
boolean createOpponent = false;
public App3(char c, boolean go) {
this.c = c;
this.go = go;
}
public void setOpponent(App3 opponent) {
this.opponent = opponent;
}
public void setCreateOpponent(boolean createOpponent) {
this.createOpponent = createOpponent;
}
public static void main(String[] args) {
App3 a = new App3('a', true);
App3 b = new App3('A', false);
Thread t1 = new Thread(a);
a.setOpponent(b);
a.setCreateOpponent(true);
b.setOpponent(a);
t1.start();
}
#Override
public synchronized void run() {
if (createOpponent) {
setCreateOpponent(false);
new Thread(opponent).start();
}
for (char i = 0; i < 26; i++) {
try {
if (go) {
System.out.println(c++);
this.wait();
synchronized (opponent) {
opponent.notify();
}
} else {
System.out.println(c++);
synchronized (opponent) {
opponent.notify();
}
this.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
You're supposed to use a boolean to control which thread prints:
Thread 1 waits for the boolean to be false. Then it prints and sets it true.
Thread 2 waits for the boolean to be true. Then it prints and sets it false.
In this way, the threads will alternate. Also, all of this will be much faster if you use signaling between threads instead of sleep:
import java.util.*;
import java.lang.*;
import java.io.*;
public class ABCThread implements Runnable {
static Object monitor = new Object();
static boolean turn = false;
char c;
final boolean myTurn;
public ABCThread(char c, boolean myTurn) {
this.c = c;
this.myTurn = myTurn;
}
#Override
public void run() {
for (char i = 0; i < 26; i++) {
synchronized(monitor) {
while (turn != myTurn) {
try {
// Note that the lock is release while I'm waiting,
// So the other thread can claim it here.
monitor.wait();
} catch (Exception e) {
}
}
System.out.println(c++);
turn = !myTurn;
monitor.notifyAll();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ABCThread('a', false));
Thread t2 = new Thread(new ABCThread('A', true));
t1.start();
t2.start();
t1.join();
t2.join();
}
}
What you need? A "shared resource" between threads.
Further: A synchronous FSM (Finite state machine)
Below is code that demonstrated how to achieve that.
public class Main
{
// The shared resource
public static class State {
private int val;
private int nStates;
// Init value and number of states.
public State(int init, int nStates) {
this.val = init;
this.nStates = nStates;
}
int get() {
return val;
}
// Define how to get to next state. For simple use case, just increase then modulo it. eg: 0, 1, 0, 1
// Avoid modulo in-case you need very very high performance.
void next() {
this.val = (this.val + 1) % nStates;
}
}
public static class ABCThread implements Runnable{
private char c;
private State s;
private int type;
public ABCThread(char c, State s, int type) {
this.c = c;
this.s = s;
this.type = type;
}
#Override
public void run() {
try {
for (char i = 0; i < 26; i++) {
// Do things synchronously
synchronized(s){
while(s.get() != type) {
// Wait for our turn.
s.wait();
}
System.out.print(c++);
// Update state
s.next();
// Notify to other threads to do their job.
s.notifyAll();
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
// Define the state.
State s = new State(0, 2);
/* Uncomment this block to have 3 synchronous threads. Will print aA1bB2...
s = new State(0, 3);
Thread t3 = new Thread(new ABCThread('1', s, 2));
t3.start();
t3.join();
*/
Thread t1 = new Thread(new ABCThread('a', s, 0));
Thread t2 = new Thread(new ABCThread('A', s, 1));
// Start threads
t1.start();
t2.start();
// Wait for these threads to finish before exit.
t1.join();
t2.join();
}
}
Quick answer:
You can't force a thread to run at a certain moment. What you can do though is let those two run "out of sync" (not related to async coding).
Thread t1 = new Thread(new ABCThread('a'));
Thread.sleep(250);
Thread t2 = new Thread(new ABCThread('A'));
The 1st thread will print about every 500 ms and the 2nd thread will print at 250, 750, 1250, etc.
Note that this would not be a correct way to solve this in real programs. But then again, you would also likely not add Thread.sleep(500) to the run method.
Better:
You need synchronization between the threads. Because you start two threads you can use a boolean.
public class ABCThread implements Runnable {
char c;
static boolean synchronizer = false;
boolean runOn;
public ABCThread(char c, boolean runOn) {
this.c = c;
this.runOn = runOn;
}
#Override
public synchronized void run() {
int count = 0;
while(count < 26)
{
if(runOn != synchronizer)
{
Thread.sleep(100);
continue;
}
count++;
synchronizer = !synchronizer;
System.out.println(c++);
}
}
Thread t1 = new Thread(new ABCThread('a', false));
Thread t2 = new Thread(new ABCThread('A', true));
Just typing this out. It might not compile.
Thread.sleep(100) is just some number. It could possibly be lower, but doesn't matter much for the question.
Even better
The previous code can run with only 2 threads! 1 will just stay stuck with synchronizer = false. If you add a third then the synchronizer won't work because it only has 2 states.
You could add an integer instead of the boolean and another integer amountOfThreads. The amountOfThreads will need to be set to the amount of threads you will start up. Then increase the atomic integer when the thread prints and if the synchronizer (the atomic int) is more than amountOfThreads, set it to 0.
Hope this helps...
public class ABCThread implements Runnable {
char c;
boolean flag;
public ABCThread(char c, boolean flag) {
this.c = c;
this.flag = flag;
}
#Override
public synchronized void run() {
for (char i = 0; i < 52; i++) {
try {
if (flag) {
System.out.println(c++);
notifyAll();
flag = false;
wait(100);
} else {
flag = true;
wait(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ABCThread('a', true));
Thread t2 = new Thread(new ABCThread('A', false));
t1.start();
t2.start();
}
}
or you can define separate methods for printing small and capital letters and run them in two separate threads
public class ABCThread {
boolean flag;
public ABCThread(boolean flag) {
this.flag = flag;
}
public static void main(String[] args) throws InterruptedException {
ABCThread abc = new ABCThread(false);
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
abc.printSmallLetters();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
abc.printCapitalLetters();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
synchronized void printSmallLetters() throws InterruptedException {
for (char i = 'a'; i < 'z'; i++) {
while (flag == true) {
wait();
}
System.out.println(i);
notifyAll();
flag = true;
}
}
synchronized void printCapitalLetters() throws InterruptedException {
for (char i = 'A'; i < 'Z'; i++) {
while (flag == false) {
wait();
}
System.out.println(i);
notifyAll();
flag = false;
}
}
}
just replace the println by print to get a series output like this
other than that everything seems to be fine,
you can see the output i got in the screenshot above
No way. The order of execution of threads cannot be controlled).You can use Thread.yield(). But yield () - tries to tell the scheduler to execute the next thread, but it stays in the RUNNABLE state.

Not getting expected result when updating AtomicInteger variable in multiple threads

In this code I'm using 10 threads updating an AtomicInteger variable. I expect the final result of Counter.getInstance().holder.n to be 1000000, but it prints out random number like 991591.
What's wrong with my code?
public class Test {
public static void main(String[] args) {
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
list.add(new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
Counter.getInstance().holder.n.incrementAndGet();
}
}
});
}
for (Thread thread : list) {
thread.start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Counter.getInstance().holder.n);
}
}
class Counter {
private static Counter counter;
Holder holder = new Holder();
public static Counter getInstance() {
if (counter == null) {
counter = new Counter();
}
return counter;
}
class Holder {
AtomicInteger n = new AtomicInteger(0);
}
}
You have two major concurrent issues here:
You don't wait for every Thread to finish work correctly. There are multiple ways to achieve that, the simplest is to use Thread.join().
Your singleton implementation doesn't seem correct. I suppose you intended to implement it with an inner class. It seems that this answer can help to understand what's happening here.
Here is the implementation that seems more or less correct.
class Test {
public static void main(String[] args) throws InterruptedException {
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
list.add(new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
Counter.getInstance().n.incrementAndGet();
}
}
});
}
for (Thread thread : list) {
thread.start();
}
for (Thread thread : list) {
thread.join();
}
System.out.println(Counter.getInstance().n);
}
}
class Counter {
public AtomicInteger n = new AtomicInteger(0);
public static Counter getInstance() {
return Holder.instance;
}
private static class Holder {
private static final Counter instance = new Counter();
}
}
You can use something like CountDownLatch as well. For example:
final int count = 10;
CountDownLatch latch = new CountDownLatch(count);
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < count; i++) {
list.add(new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
Counter.getInstance().n.incrementAndGet();
}
latch.countDown();
}
});
}
for (Thread thread : list) {
thread.start();
}
latch.await();
System.out.println(Counter.getInstance().n);

Synchronization by this doesn't prevent concurrency [duplicate]

This question already has answers here:
Threading and synchronized methods
(3 answers)
Closed 4 years ago.
I'm very novice in multithreading in java, so would be very appreciate if someone give me brief explanation of the following:
here is my code:
public class Lesson6 {
private static volatile Long value = 0L;
public static void main(String[] args) throws InterruptedException {
Thread inc = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (this){
++value;
}
}
}
});
inc.start();
Thread dec = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (this){
--value;
}
}
}
});
dec.start();
inc.join();
dec.join();
System.out.println(value);
}
}
It seems for me, that the output should be zero, but it's never zero. Debugger shows that THIS is always different from time to time as run() methods go. Why does this happen?
Thanx.
Debugger shows that THIS is always different from time to time as run() methods go
Each new Runnable is a different object so this is different in each case.
If you use a common object, the program should work.
BTW I suggest using a primitive long for the value instead of a reference to a Long
public class Lesson6 {
private static volatile long value = 0L;
public static void main(String[] args) throws InterruptedException {
final Object locked = new Object();
Thread inc = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (locked){
++value;
}
}
}
});
inc.start();
Thread dec = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (locked){
--value;
}
}
}
});
dec.start();
inc.join();
dec.join();
System.out.println(value);
}
}
prints
0

Java Thread Count doesn't work

Why is count 0?
I start the thread 1 then I start thread 2. Count should be 2000. But it shows count to be 0. Someone please explain in simple terms.
public class App {
private int count = 0;
public static void main(String[] args) {
App app = new App();
app.doWork();
}
public void doWork(){
Thread t1 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count++;
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count++;
}
}
});
t1.start();
t2.start();
System.out.println("Count is: " + count);
}
}
At the time you're printing out your thread count, the threads have not finished executing yet.
To demonstrate, add a Thread.sleep() instruction before printing out the thread count:
public class App {
private int count = 0;
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.doWork();
}
public void doWork() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
t1.start();
t2.start();
Thread.sleep(5000);
System.out.println("Count is: " + count); // Count is: 20000
}
}
Also note that operations on primitives are not thread-safe and that the count++ operation is not atomic. You should synchronize access to your count variable, or use an AtomicInteger or LongAdder instead of an int. As it stands, you might end up with a count anywhere between zero and 20,000.
Integer's increment is not safe to multithreading. You should use AtmoicInteger like this:
public class App {
private AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.doWork();
}
public void doWork() throws InterruptedException {
Thread t1 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count.getAndIncrement();
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count.getAndIncrement();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count is: " + count);
}
}
It is because you are printing count in main thread.
Main thread executed in its normal way , before child thread started.
That's why your count is 0 ,
try to print count after a while , like put Thread.sleep(2000) before printing it.
You need to make the code block which increments the count as synchronized in order to avoid the race condition.
In addition to this there are multiple ways to solve this problem-
1. Hard code Thread.sleep(miliseconds value) in Main thread. [Not recommended]
2. join() the two threads to the main Thread so that the control returns to the main thread only when the execution of the two threads is complete.
public class App implements Runnable {
private int count = 0;
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.doWork();
}
public void doWork() throws InterruptedException {
Thread t1 = new Thread(this, "Thread - 1");
Thread t2 = new Thread(this, "Thread - 2");
t1.start();
t2.start();
//1.
t1.join();
t2.join();
//2.
//Thread.sleep(1000);
System.out.println("Count is: " + count); // Count is: 2000
}
#Override
public synchronized void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
}

Getting error while implementing Threads

ERROR: local variable t is accessed from within inner class need to be declared final And local variable t1 is accessed from within the class.same with t1.start(); why do I need to declare them final?
public class sync {
public int count = 0;
public static void main(String args[]) {
sync obj = new sync();
obj.dowork();
sync obj1 = new sync();
obj1.dowork1();
System.out.println(count);
}
public void dowork() {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
t.start();
}
});
}
public void dowork1() {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
t1.start();
}
});
}
}
I did what you told me really helpful now it's just Showing: System.out.println("count"+count);
Identifier expected plus reach end of file while parsing
t and t1 objects are limited to scope of methods, make them member variables. Secondly, method calls and statements are called from inside a method..here t.start() & t1.start() are just floating loose inside class ... Same goes for print statement it
should also be called from inside a method.
Call to start method should be after the threads (t,t1) has been initialized. Currently they are used inside the initialization process.
It should be like this :
public void dowork(){
Thread t=new Thread (new Runnable (){
public void run(){
for (int i=0;i<1000;i++){
count++;}
}});
t.start();
}
Also count should be a static variable, as you cannot refer non-static variable from inside a static main method.
Your code be like, following think are corrected:
You make count variable static since it is been access with in static main method.
You trying to call Thread.start with in the run method which is wrong, since Thread.start method will call run method.
public class sync {
public static int count = 0;
public static void main(String args[]) {
sync obj = new sync();
obj.dowork();
sync obj1 = new sync();
obj1.dowork1();
System.out.println(count);
}
public void dowork() {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t.start();
}
public void dowork1() {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t1.start();
}
}
public class sync {
static int count = 0;
public static void main(String args[]) {
sync obj = new sync();
obj.dowork();
sync obj1 = new sync();
obj1.dowork1();
System.out.println(count);
}
public void dowork() {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t.start();
}
public void dowork1() {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t1.start();
}
}

Categories