I'm implementing Mutex in Java, the code shown as below, I don't why the result doesn't match my expect,
as you can see in the result that I shown, it run as unpredictable
enum MutexStatus {
FREE, BUSY
};
enum FunctionTypes {
INCREASE, DECREASE
};
class Mutex {
private MutexStatus mutexStatus;
public Mutex() {
mutexStatus = MutexStatus.FREE;
}
public void acquire() {
synchronized (this) {
while (mutexStatus == MutexStatus.BUSY)
;
mutexStatus = MutexStatus.BUSY;
}
}
public void release() {
mutexStatus = MutexStatus.FREE;
}
}
class MyThread extends Thread {
private static Mutex mutex = new Mutex();
private static Integer sharedCounter = 0;
private FunctionTypes funcType;
public MyThread(String name, FunctionTypes functionType) {
super.setName(name);
funcType = functionType;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
mutex.acquire();
switch (funcType) {
case INCREASE:
sharedCounter++;
System.out.println(Thread.currentThread().getName() + " -> "
+ sharedCounter);
break;
case DECREASE:
sharedCounter--;
System.out.println(Thread.currentThread().getName() + " -> "
+ sharedCounter);
break;
default:
break;
}
mutex.release();
}
}
}
public class MutexImplement {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread IncreaseThread = new MyThread("Increase thread",
FunctionTypes.INCREASE);
IncreaseThread.start();
MyThread DecreaseThread = new MyThread("Decrease thread",
FunctionTypes.DECREASE);
DecreaseThread.start();
}
}
The result is
>Increase thread -> 1
>Decrease thread -> 0
>Increase thread -> 1
>Decrease thread -> 0
>Decrease thread -> 1
>Increase thread -> 1
>...........
Take a look at 17.4 in http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html. The threads will have their own local copy of the variables that they share (or don't actually). As already suggested make your shared variables volatile or use some synchronization/concurrency control. You may also want to take a look at the spin loop (the while loop) and use some signalling.
Now Java has lots of constructs to do this all for you though I suspect you have been asked to create a mutex yourself. For the record try to avoid your own homebrews and try and use the provided concurrency constructs.
Related
so much confused why I get a random result while doing 'i++' in a synchronized or a locked method?
public class aaa implements Runnable {
static int count = 0;
public static void main(String[] args) {
aaa aaa = new aaa();
aaa.create();
}
public void create() {
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
aaa thread = new aaa();
executor.execute(thread);
}
executor.shutdown();
while (true){
if(executor.isTerminated()){
System.out.println("a " + count);
break;
}
}
}
#Override
public void run() {
this.test();
}
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
}
OR:
public synchronized void test() {
count++;
System.out.println(count);
}
the result is a random number sometimes 1000 sometimes 998, 999 ...etc and the print from inside the 'test' method is not in a sequence, it is like :
867
836
825
824
821
820
819
817
816
a 999
However, if it is in a synchronized block, everything looks good:
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
the result:
993
994
995
996
997
998
999
1000
a 1000
I think all of the methods above should give me the same result 1000, and the self increment should be in a sequence, but only the last method works.What is wrong with the code? Please help!!!
You are creating multiple instances of aaa, each instance creates its own ReentrantLock, and every thread in execution smoothly acquires a lock from its own instance.
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
Since there are multiple instances of aaa, each thread is running on its own instance and the synchronized method uses current object of aaa.class
public synchronized void test() {
count++;
System.out.println(count);
}
The reason for getting a proper result in this approach is, you are using the aaa.class as an object to the synchronization
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
The solution is, reuse the same lock(ReentrantLock) across all the threads. Defining the lock in the same level as the variable count would solve the issue.
You must create a single mutex, i.e.
static Lock lock = new ReentrantLock();
Your synchronized method does not work since you are creating N aaa instances then, every (non static) method is different (with their own mutex).
Your synchronized (aaa.class) works since aaa.class is the same Object for all aaa instances and methods.
Then, if you need synchronize the method be sure it is the same for all threads, e.g. if test is static will be the same for all
#Override
public void run() {
test();
}
public static synchronized void test() {
count++;
}
but you can inject a "counter class", e.g.
class Counter {
int count = 0;
// non static but synchronized for all (since they use the same `counter` object)
synchronized void inc() {
count++;
}
}
to be used for all threads
...
SyncTest thread = new SyncTest(counter); // <== the same
...
(full code)
public class SyncTest implements Runnable {
private final Counter c;
public SyncTest(Counter c) {
this.c = c;
}
static class Counter {
int count = 0;
// non static but synchronized for all (since they use the same `counter` object)
synchronized void inc() {
count++;
}
}
#Override
public void run() {
test();
}
public void test() {
this.c.inc();
}
public static void main(String[] args) {
// one counter for all
Counter counter = new Counter();
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 10000; i++) {
SyncTest thread = new SyncTest(counter);
executor.execute(thread);
}
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
System.out.println("a " + counter.count);
break;
}
}
}
}
Rule of thumb: Declare your lock variable on the next line after the variable(s) that you want to protect with it, and declare it with the same keywords. E.g.,
public class aaa implements Runnable {
static int count = 0;
static Lock countLock = new ReentrantLock();
...
If you read deeply enough into any of the other answers here, then you will see why this helps.
So my task is this:
Instantiate two object of the same class
Provide a constructor argument, to designate a thread as even and another as odd .
Start both threads right one after other
Odd thread prints odd numbers from 0 to 1000
Even thread prints even numbers from 0 to 1000
However they should be in sync the prints should be 1 , 2 , 3 , 4 .....
One number on each line
However I can't seem to get the locks to release correctly. I've tried reading some of the similar problems on here but they all use multiple classes. What am I doing wrong?
Edit: My main class is doing this -
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
and my output is -
odd: 1
even: 2
...
public class NumberPrinter extends Thread {
private String name;
private int starterInt;
private boolean toggle;
public NumberPrinter(String name) {
super.setName(name);
this.name=name;
if(name.equals("odd")) {
starterInt=1;
toggle = true;
}
else if(name.equals("even")) {
starterInt=2;
toggle = false;
}
}
#Override
public synchronized void run() {
int localInt = starterInt;
boolean localToggle = toggle;
if(name.equals("odd")) {
while(localInt<1000) {
while(localToggle == false)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = false;
notify();
}
}
else {
while(localInt<1000) {
while(localToggle == true)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = true;
notify();
}
}
}
}
The key problem here is that the two threads have no way to coordinate with each other. When you have a local variable (localToggle in this case) nothing outside the method can observe or alter its value.
If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads.
You will see examples where the shared object is an AtomicInteger, but when you use synchronized, wait() and notify(), you don't need the extra concurrency overhead built into the atomic wrappers.
Here's a simple outline:
class Main {
public static main(String... args) {
Main state = new Main();
new Thread(new Counter(state, false)).start();
new Thread(new Counter(state, true)).start();
}
int counter;
private static class Counter implements Runnable {
private final Main state;
private final boolean even;
Counter(Main state, boolean even) {
this.state = state;
this.even = even;
}
#Override
public void run() {
synchronized(state) {
/* Here, use wait and notify to read and update state.counter
* appropriately according to the "even" flag.
*/
}
}
}
}
I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely.
I finally got it working in a way that meets the standards required by my assignment.
Thank you all for your input. I'll leave the answer here for anyone who might need it.
public class Demo {
public static void main(String[] args) {
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
System.out.println("Calling thread Done");
}
public class NumberPrinter extends Thread {
private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;
public NumberPrinter(String name) {
this.name = name;
if(name.equals("even")) {
remainder=0;
}else {
remainder=1;
}
}
#Override
public void run() {
while(startNumber<max) {
synchronized(lock) {
while(startNumber%2 !=remainder) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": "+startNumber);
startNumber++;
lock.notifyAll();
}
}
}
}
consider the below code.
public class MyThread extends Thread {
int limit;
public MyThread(int limit, String name) {
super();
this.limit = limit;
this.setName(name);
}
public void run() {
printValues();
}
private synchronized void printValues() {
for (int i = 1; i < limit; i++) {
System.out.println(currentThread().getName() + " No = " + i);
}
}
}
Requirement: If a thread starts execution of printValues(), suppose it has to print till 10000. Until it completes its job, no other thread should be able to enter this method.
For this I tried Lock interface as well not able to achieve this.
can anyone throw some inputs on this?
You time will be highly appreciated.
Putting synchronized means a thread has to acquire the lock (monitor) for the object instance. If you enforce only one instance of the object it stops concurrent execution.
Alternatively you can have a static lock to do the same thing
private static final Object lock = new Object();
public void printValues() {
synchronized(lock) {
//...
}
}
I have two synchronized methods and I'm using the mediator design pattern.
I'm trying to avoid deadlocks, which is (from what I understand) for example when a thread has a lock on a variable res1 but needs a lock on variable res2. The other thread needs the lock for res1 but has the lock for res2 - resulting in a deadlock, right?
Assuming my understanding of deadlocks are correct, then my question is whether or not I have solved the issue of deadlock in this code?
I have two synchronized methods and two threads.
public class Producer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
public Producer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = (int)(Math.random()*100);
med.storeMessage(num);
System.out.println("P-" + id + ": " + num);
}
}
}
public class Consumer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
// laver kopling over til mediator
public Consumer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = med.retrieveMessage();
System.out.println("C" + id + ": " + num);
}
}
}
public class Mediator {
private int number;
private boolean slotFull = false;
public synchronized void storeMessage(int num) {
while(slotFull == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = true;
number = num;
notifyAll();
}
public synchronized int retrieveMessage() {
while(slotFull == false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = false;
notifyAll();
return number;
}
}
public class MediatorTest {
public static void main(String[] args) {
Mediator mb = new Mediator();
new Producer(mb).start();
new Producer(mb).start();
new Producer(mb).start();
new Consumer(mb).start();
new Consumer(mb).start();
}
}
for example when a thread has a lock on a variable res1 but needs a lock on variable res2
What matters is not that there are two variables, what matters is that there must be two (or more) locks.
The names "res1" and "res2" are meant to suggest two resources each of which may have one or more variables, and each of which has its own lock. Here's where you get into trouble:
final Object lock1 = new Object();
final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
// Call Thread.sleep(1000) here to simulate the thread losing its time slice.
synchronized(lock2) {
doSomethingThatRequiresBothLocks
}
}
}
public void method2() {
synchronized (lock2) {
// Do the same here 'cause you can't know which thread will get to run first.
synchronized(lock1) {
doSomethingElseThatRequiresBothLocks()
}
}
}
If thread A calls method1(), there is a very small chance that it could lose its time slice (i.e., turn to run) just after it successfully locks lock1, but before it locks lock2.
Then, while thread A is waiting its turn to run again, thread B calls method2(). Thread B will be able to lock lock2, but then it gets stuck because lock1 is locked by thread A. Furthermore, when thread A gets to run again, it will immediately be blocked when it tries to lock lock2 which is owned by thread B. Neither thread will ever be able to continue from that point.
In real code, it's never so obvious. When it happens in real-life, it usually is because of some unforseen interaction between code from two or more different modules that may not even be aware of each other, but which access the same common resources.
Your understanding of the basic deadlock problem is correct. With your second question about validity of your solution to the deadlock problem, you've only got 1 lock, so I'd say "yes" by default, since the deadlock you described isn't possible in this situation
I agree with what #ControlAltDel has said. And your understanding of a deadlock matches mine. Whereas there are a few different ways in which a deadlock can manifest itself, the way you describe -- inconsistently acquiring multiple monitors by involved threads (methods) causes deadlock.
Another way would be to (for example,) sleep while holding a lock. As you coded correctly, when the producer finds that slotFull = true, it waits, giving up the lock, so the other thread (consumer, which is sharing the same instance of Mediator with producer) can make progress potentially causing this thread also to make progress after it gets a notification. If you had chosen to call Thread.sleep() instead (naively hoping that someone will cause the sleep to end when the condition would be false), then it would cause a deadlock because this thread is sleeping, still holding the lock, denying access to the other thread.
Every object has one lock which restrict multiple threads to access same block of code or method when you use synchronized keyword.
Coming to your problem, it will not deadlock.
If you have two independent attribute in a class shared by multiple threads, you must synchronized the access to each variable, but there is no problem if one thread is accessing one of the attribute and another thread accessing the other at the same time.
class Cinema {
private long vacanciesCinema1; private long vacanciesCinema2;
private final Object controlCinema1, controlCinema2;
public Cinema() {
controlCinema1 = new Object();
controlCinema2 = new Object();
vacanciesCinema1 = 20;
vacanciesCinema2 = 20;
}
public boolean sellTickets1(int number) {
synchronized (controlCinema1) {
if (number < vacanciesCinema1) {
vacanciesCinema1 -= number;
return true;
} else {
return false;
}
}
}
public boolean sellTickets2(int number) {
synchronized (controlCinema2) {
if (number < vacanciesCinema2) {
vacanciesCinema2 -= number;
return true;
} else {
return false;
}
}
}
public boolean returnTickets1(int number) {
synchronized (controlCinema1) {
vacanciesCinema1 += number;
return true;
}
}
public boolean returnTickets2(int number) {
synchronized (controlCinema2) {
vacanciesCinema2 += number;
return true;
}
}
public long getVacanciesCinema1() {
return vacanciesCinema1;
}
public long getVacanciesCinema2() {
return vacanciesCinema2;
}
}
class TicketOffice1 implements Runnable {
private final Cinema cinema;
public TicketOffice1(Cinema cinema) {
this.cinema = cinema;
}
#Override
public void run() {
cinema.sellTickets1(3);
cinema.sellTickets1(2);
cinema.sellTickets2(2);
cinema.returnTickets1(3);
cinema.sellTickets1(5);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
}
}
public class CinemaMain {
public static void main(String[] args) {
Cinema cinema = new Cinema();
TicketOffice1 ticketOffice1 = new TicketOffice1(cinema);
Thread thread1 = new Thread(ticketOffice1, "TicketOffice1");
TicketOffice2 ticketOffice2 = new TicketOffice2(cinema);
Thread thread2 = new Thread(ticketOffice2, "TicketOffice2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Room 1 Vacancies: %d\n", cinema.getVacanciesCinema1());
System.out.printf("Room 2 Vacancies: %d\n", cinema.getVacanciesCinema2());
}
}
public class ThreadTest
{
public static Integer i = new Integer(0);
public static void main(String[] args) throws InterruptedException
{
ThreadTest threadTest = new ThreadTest();
Runnable odd = threadTest.new Numbers(1, "thread1");
Runnable even = threadTest.new Numbers(0, "thread2");
((Thread) odd).start();
((Thread) even).start();
}
class Numbers extends Thread
{
int reminder;
String threadName;
Numbers(int reminder, String threadName)
{
this.reminder = reminder;
this.threadName = threadName;
}
#Override
public void run()
{
while (i < 20)
{
synchronized (i)
{
if (i % 2 == reminder)
{
System.out.println(threadName + " : " + i);
i++;
i.notify();
}
else
{
try
{
i.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
}
You can't synchronize on i because it changes during execution of your program.
Since Integer in Java is immutable, after executing i++ i will contain a reference to another object, not the object you have synchronized on. So, you can't call wait()/notify() on this new object, because these methods may be only called on the object you are synchronized on, otherwise you get IllegalMonitorStateException.
You need to synchronize on some other object that doesn't change during execution. For example, you may create a separate object for this purpose:
public class ThreadTest {
public static Integer i = new Integer(0);
public static Object lock = new Object();
...
class Numbers extends Thread {
...
#Override
public void run() {
...
synchronized (lock) {
...
lock.notify();
...
lock.wait();
...
}
}
}
}
This line:
i++;
is equivalent to:
i = i + 1;
which (due to autoboxing) becomes something like:
i = new Integer(i.intValue() + 1);
So, when you call i.notify() you are synchronized on the old i, not the new one.
I'd suggest changing i into an ordinary int variable, and create a separate object to synchronize on:
static int i = 0;
static Object iMonitor = new Object();
As documentation states the exception is thrown when
the current thread is not the owner of the object's monitor
It also states that
This method should only be called by a thread that is the owner of this object's monitor.
And this condition can be obtained by
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
You could try calling the wait method from inside the class that uses i. This could be done by extending the class and writing two new methods for notify and wait..
You cannot put wait() and notify() in the same synchronized block because that will just cause a deadlock. Make sure only the wait and notify functions are wrapped with a synchronized block like this:
synchronized (i) {
i.wait(); // or i.notify();
}