slides - lab chapter 5 - java threads
TRANSCRIPT
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
1/128
Operating
Systems1
Lab 05 Java Threads
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
2/128
Operating
Systems2
Outline
Creating a Java Thread
Synchronized Keyword
Wait and Notify
High Level Cuncurrency Objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
3/128
Operating
Systems3
Creating a Java thread
Java threads are a way to have different parts of yourprogram running at the same time.
For example, you can create an application that accepts
input from different users at the same time, each userhandled by a thread.
Also, most networking applications involve threads
you would need to create a thread that would wait for incomingmessages while the rest of your program handles your outgoing
messages.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
4/128
Operating
Systems4
Creating a Java thread
There are two ways to create a java thread
Extending the Thread class
Implementing the runnable interface
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
5/128
Operating
Systems5
Basic threads
We will create a thread that simply prints out a number 500times in a row.
class MyThread extends Thread {
int i;MyThread(int i) {this.i = i;
}public void run() {
for (int ctr=0; ctr < 500; ctr++) {System.out.print(i);
}}
}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
6/128
Operating
Systems6
Basic threads
To show the difference between parallel and non-parallelexecution, we have the following executableMyThreadDemo class
class MyThreadDemo {public static void main(String args[]) {
MyThread t1 = new MyThread(1);MyThread t2 = new MyThread(2);MyThread t3 = new MyThread(3);t1.run();t2.run();
t3.run();System.out.print("Main ends");
}}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
7/128
Operating
Systems7
Basic threads
Upon executing MyThreadDemo, we get output that lookslike this
$ java MyThreadDemo
1111111111...22222222.....33333......Main ends
As can be seen, our program first executed t1's run method,which prints 500 consecutive 1's.
After that t2's run method, which prints consecutuve 2's, andso on.
Main ends appears at the last part of the output as it is thelast part of the program.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
8/128
Operating
Systems8
Basic threads
What happened was serial execution, no multithreadedexecution occurred
This is because we simply called MyThread's run() method
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
9/128
Operating
Systems9
Basic threads
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
10/128
Operating
Systems10
Basic threads
To start parallel execution, we call MyThread's start()method, which is built-in in all thread objects.
class MyThreadDemo {
public static void main(String args[]) {MyThread t1 = new MyThread(1);MyThread t2 = new MyThread(2);MyThread t3 = new MyThread(3);t1.start();t2.start();t3.start();
System.out.print("Main ends");}}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
11/128
OperatingSystems
11
Basic threads
When we run MyThreadDemo we can definitely see thatthree run methods are executing at the same time
> java MyThreadDemo
111111111122331122321122333331111Main ends111333222...
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
12/128
OperatingSystems
12
Basic threads
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
13/128
OperatingSystems
13
Basic threads
Note the appearance of the "Main ends" string in the middleof the output sequence
> java MyThreadDemo
111111111122331122321122333331111Main ends111333222...
This indicates that the main method has already finishedexecuting while thread 1, thread 2 and thread 3 are stillrunning.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
14/128
OperatingSystems
14
Basic threads
Running a main method creates a thread.
Normally, your program ends when the main thread ends.
However, creating and then running a thread's start method
creates a whole new thread that executes its run() methodindependent of the main method.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
15/128
OperatingSystems
15
Implementing runnable
Another way to create a thread is to implement theRunnable interface.
This may be desired if you want your thread to extendanother class.
By extending another class, you will be unable to extend classthread as Java classes can only extend a single class.
However, a class can implement more than one interface.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
16/128
OperatingSystems
16
Implementing runnable
The following is our MyThread class created byimplementing the runnable interface.
class MyThread implements Runnable {
... }
Classes that implement Runnable are instantiated in adifferent way.
Thread t1 = new Thread(new MyThread(1));
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
17/128
OperatingSystems
17
Implementing runnable
Note that implementing an interface requires you to defineall the methods in the interface
For the Runnable interface, you are required in yourimplementing class to define the run() method or yourprogram will not run.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
18/128
OperatingSystems
18
Pausing threads
Threads can be paused by the sleep() method.
For example, to have MyThread pause for half a secondbefore it prints the next number, we add the following linesof code to our for loop.
for (int ctr=0; ctr < 500; ctr++) {System.out.print(i);try {
Thread.sleep(500); // 500 miliseconds} catch (InterruptedException e) { }
}
Thread.sleep() is a static method of class thread and can beinvoked from any thread, including the main thread.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
19/128
OperatingSystems
19
Pausing threadsfor (int ctr=0; ctr < 500; ctr++) {
System.out.print(i);try {
Thread.sleep(500); // 500 miliseconds} catch (InterruptedException e) { }
}
The InterruptedException is an unchecked exeception that isthrown by code that stops a thread from running.
Unchecked exception causing lines must be enclosed in a try-catch,in this case, Thread.sleep().
An InterruptedException is thrown when a thread is waiting,sleeping, or otherwise paused for a long time and anotherthread interrupts it using the interrupt() method in classThread.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
20/128
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
21/128
OperatingSystems
21
Outline
Creating a Java Thread
Synchronized Keyword
Wait and Notify
High Level Cuncurrency Objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
22/128
OperatingSystems
22
The Critical Section Problem
This section we will find out how to implement a solution tothe critical section problem using Java
Recall that only a single process can enter its criticalsection, all other processes would have to wait
No context switching occurs inside a critical section
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
23/128
OperatingSystems
23
The Critical Section Problem
Instead of printing a continuous stream of numbers,MyThread calls a print10() method in a class MyPrinter
print10() prints 10 continuous numbers on a single line before anewline.
Our goal is to have these 10 continuous numbers printedwithout any context switches occuring.
Our output should be:
...1111111111
1111111111222222222233333333331111111111
...
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
24/128
OperatingSystems
24
MyPrinter
We define a class MyPrinter that will have our print10()method
class MyPrinter {
public void print10(int value) {for (int i = 0; i < 10; i++) {
System.out.print(value);}System.out.println(""); // newline after 10 numbers
}}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
25/128
OperatingSystems
25
MyThread (revised)
Instead of printing numbers directly, we use the print10()method in MyThread, as shown by the following
class MyThread extends Thread {
int i;MyPrinter p;MyThread(int i) {
this.i = i;p = new MyPrinter();
}public void run() {
for (int ctr=0; ctr < 500; ctr++) {p.print10(i);
}}
}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
26/128
OperatingSystems
26
MyThreadDemo (revised)
First, we will try to see the output of just a single threadrunning.
class MyThreadDemo {
public static void main(String args[]) {MyThread t1 = new MyThread(1);// MyThread t2 = new MyThread(2);// MyThread t3 = new MyThread(3);t1.start();// t2.start();// t3.start();
System.out.print("Main ends");}}
We comment out
the other threadsfor now...
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
27/128
OperatingSystems
27
MyThreadDemo
When we run our MyThreadDemo, we can see that theoutput really does match what we want.
> java MyThreadDemo1111111111
1111111111111111111111111111111111111111
...
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
28/128
OperatingSystems
28
MyThreadDemo (revised 2)
However, let us try to see the output with other threads.
class MyThreadDemo {
public static void main(String args[]) {MyThread t1 = new MyThread(1);MyThread t2 = new MyThread(2);MyThread t3 = new MyThread(3);t1.start();t2.start();t3.start();
System.out.print("Main ends");}}
We run all three
threads
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
29/128
OperatingSystems
29
MyThreadDemo
Our output would look like the following
> java MyThreadDemo11111111111111122222221111
22233333332...
We do not achieve our goal of printing 10 consecutivenumbers in a row
all three threads are executing the print10's method at the same
time, thus having more than one number appearing on a single line.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
30/128
OperatingSystems
30
Critical Section Problem
To achieve our goal there should not be any contextswitches happening inside print10()
Only a single thread should be allowed to execute inside print10()
As can be seen, this is an example of the critical sectionproblem
To solve this, we can use some of the techniques discussedin our synchronization chapter
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
31/128
OperatingSystems
31
Synchronized keyword
Now we will discuss Java'ssolution to the criticalsection problem
Java uses a monitor
construct Only a single thread may run
inside the monitor
Even if P2 is calling method2(), ithas to wait for P1 to finish
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
32/128
OperatingSystems
32
Synchronized keyword
To turn an object into a monitor, simply put the synchronizedkeyword on your method definitions
Only a single thread can run any synchronized method in an object
class MyPrinter {public synchronized void print10(int value) {
for (int i = 0; i < 10; i++) {System.out.print(value);
}System.out.println(""); // newline after 10 numbers
}}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
33/128
OperatingSystems
33
Still not working!
However, even if we did turn our print10() method into asynchronized method, it will still not work
> java MyThreadDemo1111111111
111112222222111122233333332...
To find out how to make it work, we need to first find outhow the synchronized keyword works
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
34/128
OperatingSystems
34
Intrinsic locks
Every object in Java has an intrinsic lock
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
35/128
OperatingSystems
35
Intrinsic locks
When a thread tries to run a synchronized method, it firsttries to get a lock on the object
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
36/128
OperatingSystems
36
Intrinsic locks
If a thread is successful, then it owns the lock and executesthe synchronized code.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
37/128
OperatingSystems
37
Intrinsic locks
Other threads cannot run the synchronized code becausethe lock is unavailable
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
38/128
OperatingSystems
38
Intrinsic locks
Threads can only enter once the thread owning the lockleaves the synchronized method
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
39/128
OperatingSystems 39
Intrinsic Locks
Waiting threads would then compete on who gets to go next
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
40/128
OperatingSystems 40
MyThreadDemo Failure
So why doesn't our example work?
Because each thread has its own copy of the MyPrinterobject!class MyThread extends Thread {
int i;MyPrinter p;MyThread(int i) {
this.i = i;p = new MyPrinter(); // each MyThread creates its own MyPrinter!
}public void run() {
for (int ctr=0; ctr < 500; ctr++) {p.print10(i);
}}
}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
41/128
OperatingSystems 41
Different Locks
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
42/128
OperatingSystems 42
Important
Recall our definition of synchronized methods
Only a single thread can run any synchronized method in an object
Since each thread has its own MyPrinter object, then nolocking occurs
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
43/128
OperatingSystems43
Solution
So, to make it work, all threads must point to the sameMyPrinter object
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
44/128
OperatingSystems44
Solution
Note how all MyThreads now have the same MyPrinterobject
class MyThread extends Thread {int i;MyPrinter p;MyThread(int i, MyPrinter p) {
this.i = i; this.p = p}public synchronized void run() {
for (int ctr=0; ctr < 500; ctr++) {p.print10(i);
}}
}
class MyThreadDemo {public static void main(String args[]) {
MyPrinter p = new MyPrinter();MyThread2 t1 = new MyThread2(1,p);
MyThread2 t2 = new MyThread2(2,p);MyThread2 t3 = new MyThread2(3,p);t1.start();t2.start();t3.start();
}}
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
45/128
OperatingSystems45
Solution
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
46/128
OperatingSystems46
Locks and Doors
A way to visualize it is that all Java objects can be doors
A thread tries to see if the door is open
Once the thread goes through the door, it locks it behind it,
No other threads can enter the door because our first thread haslocked it from the inside
Other threads can enter if the thread inside unlocks the door andgoes out
Lining up will only occur if everyone only has a single door to thecritical region
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
47/128
OperatingSystems47
Synchronized methods
Running MyThreadDemo now correctly shows synchronizedmethods at work
>java MyThreadDemo11111111111111111111111111111122222222223333333333...
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
48/128
Operating
Systems48
Remember
Only a single thread can run any synchronized method in anobject
If an object has a synchronized method and a regular method, onlyone thread can run the synchronized method while multiple threadscan run the regular method
Threads that you want to have synchronized must share thesame monitor object
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
49/128
Operating
Systems49
Synchronized blocks
Aside from synchronized methods, Java also allows forsynchronized blocks.
You must specify what object the intrinsic lock comes from
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
50/128
Operating
Systems50
Synchronized blocks
Our print10() implementation, done using synchronizedstatements, would look like this
class MyPrinter {
public void print10(int value) {synchronized(this) {for (int i = 0; i < 10; i++) {
System.out.print(value);}System.out.println(""); // newline after 10 numbers
}}}
We use a MyPrinter object for thelock, replicating what the
synchronized method does
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
51/128
Operating
Systems51
Synchronized blocks
Synchronized blocks allow for flexibility, in the case if wewant our intrinsic lock to come from an object other than thecurrent object.
For example, we could define MyThread's run method to
perform the lock on the MyPrinter object before callingprint10
class MyThread extends Thread {MyPrinter p;...public void run() {
for (int i = 0; i < 100; i++) {
synchronized(p) {p.print10(value);
}}}}
Note that any linesbefore and after oursynchronized block can
be executedconcurrently by threads
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
52/128
Operating
Systems52
Multiple locks
Also, the use of the synchronized block allows for moreflexibility by allowing different parts of code to be locked withdifferent objects.
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
53/128
Operating
Systems53
Multiple locks
For example, consider a modified MyPrinter which has twomethods, which we'll allow to run concurrentlyclass MyPrinter {
Object lock1 = new Object();Object lock2 = new Object();public void print10(int value) {
synchronized(lock1) {for (int i = 0; i < 10; i++) {
System.out.print(value);}System.out.println(""); // newline after 10 numbers
}}
public int squareMe(int i) {synchronized (lock2) {return i * i;
}}
}
The blocks inside print10()and squareMe() can run atthe same time because theyuse different objects for theirlocking mechanism
Synchronization still applies.For example only a singlethread can run thesynchronized block insquareMe() at any point intime
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
54/128
Operating
Systems54
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
55/128
Operating
Systems55
Outline
Creating a Java Thread
Synchronized Keyword
Wait and Notify
High Level Cuncurrency Objects
P d C bl
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
56/128
Operating
Systems56
Producer-Consumer problem
We will now discuss a solution to the Producer-Consumerproblem.
Instead of using beer, the producer will store in a sharedstack a random integer value which will be retrieved by the
consumer process.
P d C
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
57/128
Operating
Systems57
Producer-Consumer
P d C C d
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
58/128
Operating
Systems58
Producer-Consumer Code
P d C
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
59/128
Operating
Systems59
Producer-Consumer
As can be seen, we would need to have a place to store ourarray of integers and our top variable, which should beshared among our producer and consumer.
MAXCOUNT is the maximum number of items the Producerproduces
We'll assume the maximum array size of 10000 for now
class SharedVars {final int MAXCOUNT = 100;int array[] = new int[10000];
int top;
// }
P d C
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
60/128
Operating
Systems60
Producer-Consumer
To keep things object-oriented, we will place the code forplacing values in the stack and getting values in the stack inour SharedVars class
Our next slide shows our implementation
Sh dV
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
61/128
Operating
Systems
61
class SharedVars {final int MAXCOUNT = 100;int array[] = new int[10000];int top;
// method for inserting a valuepublic void insertValue(int value) {
if (top < array.length) {
array[top] = value;top++;
}}// method for getting a valuepublic int getValue() {
if (top > 0) {top--;
return array[top];}else
return -1;}}
SharedVars
SharedVars
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
62/128
Operating
Systems
62
SharedVars
SharedVars insertValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
63/128
Operating
Systems
63
SharedVars insertValue()
SharedVars insertValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
64/128
Operating
Systems
64
SharedVars insertValue()
SharedVars insertValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
65/128
Operating
Systems
65
SharedVars insertValue()
SharedVars insertValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
66/128
Operating
Systems
66
SharedVars insertValue()
SharedVars insertValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
67/128
Operating
Systems
67
SharedVars insertValue()
SharedVars getValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
68/128
Operating
Systems
68
SharedVars getValue()
SharedVars getValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
69/128
Operating
Systems
69
SharedVars getValue()
SharedVars getValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
70/128
Operating
Systems
70
SharedVars getValue()
SharedVars getValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
71/128
Operating
Systems
71
SharedVars getValue()
SharedVars getValue()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
72/128
Operating
Systems
72
SharedVars getValue()
Producer-Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
73/128
Operating
Systems
73
Producer Consumer
Now we will slowly build our Producer and Consumer class
We can say that our Producer and Consumer should beimplemented as threads.
Thus we have our code below, including a class that starts these
threadsclass Producer extends Thread {
public void run() {}
}
class Consumer extends Thread {public void run() {}
}
class PCDemo {
public static void main(String args[]) {Producer p = new Producer();Consumer c = new Consumer();p.start();c.start();
}}
Producer-Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
74/128
Operating
Systems
74
Producer Consumer
Producer and Consumer should have the same SharedVarsobject
class Producer extends Thread {SharedVars sv;Producer(SharedVars sv) {
this.sv = sv;}public void run() {}
}
class Consumer extends Thread {SharedVars sv;Consumer(SharedVars sv) {
this.sv = sv;}public void run() {}
}
class PCDemo {public static void main(String args[]) {
SharedVars sv = new SharedVars();Producer p = new Producer(sv);Consumer c = new Consumer(sv);p.start();c.start();
}}
Producer-Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
75/128
Operating
Systems
75
Producer Consumer
There is no more need to modify our PCDemo class so wewill not show it anymore.
Producer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
76/128
Operating
Systems
76
Producer
We want our producer to produce a random integer andstore it in SharedVars. Thus our Producer code would looklike this
class Producer extends Thread {SharedVars sv;
Producer(SharedVars sv) {this.sv = sv;}public void run() {
int value = (int)(Math.random() * 100); // random value from 0 to 100sv.insertValue(value);System.out.println("Producer: Placing value: " + value);
}
}
Producer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
77/128
Operating
Systems
77
Producer
We want our Producer to do this a hundred times, so we willadd a loop to our code
class Producer extends Thread {SharedVars sv;Producer(SharedVars sv) {
this.sv = sv;}public void run() {
for (int i = 0; i < 100; i++) {int value = (int)(Math.random() * 100); // random value from 0 to 100sv.insertValue(value);System.out.println("Producer: Placing value: " + value);
}
}}
Producer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
78/128
Operating
Systems
78
Producer
Finally, twe have our producer pause for a maximum of 5seconds each time it places a value
class Producer extends Thread {SharedVars sv;Producer(SharedVars sv) {
this.sv = sv;
}public void run() {
for (int i = 0; i < 100; i++) {int value = (int)(Math.random() * 100); // random value from 0 to 100sv.insertValue(value);System.out.println("Producer: Placing value: " + value);
try { Thread.sleep((int)(Math.random() * 5000)); // sleep 5s max} catch (InterruptedException e) { }
}}
}
Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
79/128
Operating
Systems
79
Co su e
Now, we want our consumer to get a value from SharedVars
class Consumer extends Thread {SharedVars sv;Consumer(SharedVars sv) {
this.sv = sv;}public void run() {
int value = sv.getValue();System.out.println("Consumer: I got value:" + value);
}}
Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
80/128
Operating
Systems
80
We want to get a value 100 times
class Consumer extends Thread {SharedVars sv;Consumer(SharedVars sv) {
this.sv = sv;}public void run() {
for (int i = 0; i < 100; i++) {int value = sv.getValue();System.out.println("Consumer: I got value:" + value);
}}
}
Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
81/128
Operating
Systems
81
Finally, just like producer, we pause for a maximum of 5seconds on each loop
class Consumer extends Thread {SharedVars sv;Consumer(SharedVars sv) {
this.sv = sv;}public void run() {
for (int i = 0; i < 100; i++) {int value = sv.getValue();System.out.println("Consumer: I got value:" + value);
try {
Thread.sleep((int)(Math.random() * 5000)); // sleep 5s max} catch (InterruptedException e) { }
}}
}
Race Condition
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
82/128
Operating
Systems
82
As was discussed in a previous chapter, we try to avoid arace condition between insertValue() and getValue()
Consumer getValue(): top = top 1
Producer insertValue(): array[top] = value // this would overwrite an existing value!Producer insertValue(): top = top + 1Consumer getValue(): return array[top] // consumer returns an already returned value
Race Condition
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
83/128
Operating
Systems
83
Race Condition
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
84/128
Operating
Systems
84
We do not want getValue() and insertValue() to run at thesame time
Therefore, we modify SharedVars to use synchronizedblocks
We could also use synchronized methods but we need some non-synchronized commands
Synchronized SharedVars
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
85/128
Operating
Systems
85
class SharedVars {final int MAXCOUNT = 100;
int array[] = new int[10000];int top;
public void insertValue(int value) { // method for inserting a valuesynchronized(this) {
if (top < array.length) {array[top] = value;top++;
}}
}public int getValue() { // method for getting a value
synchronized(this) {if (top > 0) {
top--;return array[top];
}else
return -1;}
}}
y
Synchronized SharedVars
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
86/128
Operating
Systems
86
Synchronized SharedVars
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
87/128
Operating
Systems
87
Producer-Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
88/128
Operating
Systems
88
Upon executing our program, the output of our code wouldlook something like this:
Producer inserts value: 15Consumer got: 15Consumer got: -1Producer inserts value: 50Producer inserts value: 75
Consumer got: 75...
Note that both Consumer and Producer are running at thesame time.
Got -1?
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
89/128
Operating
Systems
89
Producer inserts value: 15
Consumer got: 15Consumer got: -1Producer inserts value: 50Producer inserts value: 75Consumer got: 75...
Notice that, if we try to get a value from the array and thereisn't any, we return a value -1.
You can see this clearly if you increase the Producer delay to 10s.
Producer adds a value every 10s, consumer gets one every 5s
Wouldn't it be better if we have our Consumer wait for theProducer to produce something instead of just getting -1?
Busy wait
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
90/128
Operating
Systems
90
We could implement a busy wait for this
public int getValue() {while (top
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
91/128
Operating
Systems
91
A better solution is to use the wait() method, defined in classObject, and is therefore inherited by all objects
A thread invoking wait() will suspend the thread
However, a thread invoking wait() must own the intrinsic lock
of the object it is calling wait() from If we are going to call this.wait() it has to be in synchronized(this)
block
Also, as with all methods that suspend thread execution, likejoin() and sleep(), our wait() method must be in a try-catch
block that catches InterruptedExceptions.
The wait() method
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
92/128
Operating
Systems
92
// called by Consumer threadpublic int getValue() {
synchronized(this) {if (top
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
93/128
Operating
Systems
93
All threads that call wait() on an object are placed in a poolof waiting threads for that object.
Execution resumes when another thread calls the notify()method of the object our first thread is waiting on
The notify() method is defined in class Object. All objects have wait() and notify()
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
94/128
Operating
Systems
94
For our example, our producer thread, after inserting on anempty array, would notify the consumer thread that it hasplaced a value in our array by calling the notify() method onthe SharedVars object
Recall that Producer and Consumer both have a reference to the
same SharedVars object.
The producer calling notify() from insertValue() would inform any theconsumer waiting on the same SharedVar object.
The notify() method
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
95/128
Operating
Systems
95
// called by producerpublic void insertValue(int value) {
synchronized(this) {if (top < array.length) {
array[top] = value;
top++;if (top == 1) { // we just inserted on an empty array
this.notify(); // notify sleeping thread}
}}
}
class SharedVars {final int MAXCOUNT = 100;int array[] = new int[10000];int top;
Final SharedVars
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
96/128
Operating
Systems96
int top;
public void insertValue(int value) {synchronized(this) {
if (top < array.length) {array[top] = value;top++;if (top == 1) { // we just inserted on an empty array
this.notify(); // notify any sleeping thread}
}
}}
public int getValue() {synchronized(this) {
if (top
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
97/128
Operating
Systems97
When the notify() method of an object is called, then a singlewaiting thread on that object is signaled to get ready toresume execution.
After our Producer thread exists insertValue and releasesthe lock, our Consumer thread gets the lock once again andresumes its execution.
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
98/128
Operating
Systems98
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
99/128
Operating
Systems99
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
100/128
Operating
Systems100
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
101/128
Operating
Systems101
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
102/128
Operating
Systems102
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
103/128
Operating
Systems103
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
104/128
Operating
Systems104
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
105/128
Operating
Systems105
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
106/128
Operating
Systems106
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
107/128
Operating
Systems107
Another method called notifyAll() notifies all the waitingthreads.
These waiting threads would then compete to see whichsingle thread resumes execution, the rest of the threadswould once again wait.
Producer-Consumer
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
108/128
Operating
Systems108
If you run the demo program again, you can see that, even ifthe producer is slow, the consumer waits until the producergives out a value before getting that value
Note that you must also consider inserting on a full array
Producer must wait until consumer has taken away some valuesbefore inserting
We will leave the implementation of this as an exercise
Wait() and notify()
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
109/128
Operating
Systems109
Note that this same thing must occur on inserting on a fullarray
Producer must wait until consumer has taken away some valuesbefore inserting
We will leave the implementation of this as an exercise.
Outline
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
110/128
Operating
Systems110
Creating a Java Thread Synchronized Keyword
Wait and Notify
High Level Cuncurrency Objects
High level concurrency objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
111/128
Operating
Systems111
Since Java 1.5, additional classes have been added in thejava.util.concurrent package that assist in the creation andmanipulation of threads.
These high-level concurrency objects are
Lock objects
Executors
Concurrent Collections
Atomic Variables
Lock objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
112/128
Operating
Systems112
Any object in Java can be used as a lock forsynchronization. However, the java.util.concurrent.lockspackage defines classes that have additional lockingfeatures.
The basic interface of this package is the Lock interface.
Lock objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
113/128
Operating
Systems113
An object of type Lock can only be owned by a single threadat a time.
To aquire a lock, a thread must call its lock() method.
To release a lock, it must call its unlock() method.
In summary, instead of the implicit locking and unlocking ofa synchronized block or method, a lock provides theflexibility of manually calling lock() and unlock() methods.
Lock objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
114/128
Operating
Systems114
A Lock also has a tryLock() method. This tryLock() method returns a true or false value,
true if it managed to get the lock, false otherwise.
The program does not block if tryLock() does not succeed,
in contrast to the lock() method, This is the behavior of a thread if it tries to enter a sychronized block
or method.
In addition, a different version of tryLock() allows you tospecify the amount of time the thread waits to establish a
lock before it returns true or false.
Lock objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
115/128
Operating
Systems115
The folowing is an implementation of MyPrinter with Locksimport java.util.concurrent.locks.*;class MyPrinter {
final Lock l = new ReentrantLock(); // ReentrantLock is an implementation// of the Lock interface
public void print10(int value) {boolean gotLock = false;while(!gotLock) {
gotLock = l.tryLock();if (!gotLock) {
System.out.println("Unable to get lock, try again next time");try {
Thread.sleep((int)(Math.random() * 1000)); // wait until try again} catch (InterruptedException e) { }
}}for (int i = 0; i < 10; i++) {
System.out.print(value);}System.out.println(""); // newline after 10 numbersl.unlock();
}}
Lock objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
116/128
Operating
Systems116
Wait() and notify() can be called from lock objects using aConditions object
A Conditon object can be extracted from a lock using itsnewCondition() method
Conditions have an await() method which simulates wait()
A signal() method is the equivalent of notify() which notify'sobjects awaiting on that lock.
Lock objects
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
117/128
Operating
Systems117
The following slide shows our SharedVars class that usesLocks and Conditions
import java.util.concurrent.lock.*;class SharedVars {
final Lock mylock = new ReentrantLock();final Condition notEmpty = mylock.getCondition();final int MAXCOUNT = 100;int array[] = new int[10000];
Advanced SharedVars
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
118/128
Operating
Systems118
int top;
public void insertValue(int value) {mylock.lock();
if (top < array.length) {array[top] = value;top++;if (top == 1) { // we just inserted on an empty array
notEmpty.signal(); // notify any sleeping thread
}}
mylock.unlock();}public int getValue() {
mylock.lock();if (top
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
119/128
Operating
Systems119
Whenever we create a thread, we manually state when thatthread is executed. For instance, given the following thread:
class MyThread implements Runnable { ... }
We manually start the thread by the two commands:
Thread t1 = new Thread(mt1);
t1.start();
Executors
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
120/128
Operating
Systems120
An implementing class of the Executor interface abstractsthread starting from the programmer.
For instance, instead of the above code, we have thefollowing:
MyThread mt1 = new MyThread();
Executor e = new ThreadPoolExecutor(10);
e.execute(mt1);
e.execute(otherThreads);
Executors
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
121/128
Operating
Systems121
Our example uses the ThreadPoolExecutor class. This class runs our inputted threads (via the execute()
method) via a ready pool of execution threads (in this case,10 working threads).
These execution threads reduce the overhead needed forthread creation
a thread is mearly passed as a parameter to an already runningworker thread for execution.
Executors
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
122/128
Operating
Systems122
The ScheduledThreadPoolExecutor class, has methods thatallow for a partciular thread to start at a certain time of theday, or be repeated periodically.
Concurrent Collections
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
123/128
Operating
Systems123
The java.util.concurrent package includes collection classesthat can be used with multithreaded programs use withouthaving to worry about synchronization problems.
For instance, the BlockingQueue class creates a first-in-firstout queue that automatically blocks threads when they try to
add to a full queue or retreve values from an empty one. Execution automatically resumes when another thread
removes a value from a full queue or adds data to an emptyone.
Atomic Variables
A h i P d C bl th
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
124/128
Operating
Systems124
As we have seen in our Producer-Consumer problem, thefollowing commands must be executed without anyinterleaving. :
array[top] = ;
top++;
This is called atomic execution, where each command mustbe executed as a single whole.
Atomic Variables
H i l d t t i C id
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
125/128
Operating
Systems125
However, even single commands are not atomic. Considerthe command top++
Top++ is divided into three parts when run on the CPU
1. Get the value of top
2. Add 1 to that value
3. Save that value to the address of top.
Atomic Variables
All th th d t b t d ith t
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
126/128
Operating
Systems126
All these three commands must be executed without anyinterleaving commands from other threads.
One way around this is to have a synchronized incrementmethod.
class SharedVars {
int top;
public synchronized inctop() {
top++;
}
}
Atomic Variables
Most of the other arithmetic operations are sadl non
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
127/128
Operating
Systems127
Most of the other arithmetic operations are sadly, non-atomic as well
This means that, when dealing with shared variables, anymanipulation must be in a synchronized block
This includes even assignment statements.
To avoid this tediousness, the java.util.concurrent.atomicpackage provides already thread-safe classes.
Atomic Variables
For instance the AtomicInteger class provides some of the
-
7/31/2019 Slides - Lab Chapter 5 - Java Threads
128/128
Operating
Systems128
For instance, the AtomicInteger class provides some of themethods below:
void incrementAndGet() - performs an increment operationatomically
void addAndGet(int delta) adds delta to the AtomicInteger
atomically. There are also implemetnations like this for an integer array
or an object reference variable.