Monday, October 18, 2010

multithreading

Multithreading in Linux

mutex

mutex.hh


Critical Section

livelock

Multithreading in Windows

thread.hh
pthread.h


Pthread

pthread_setschedparam(pthread_self(), SCHED_OTHER, &sched);

struct Grabber_thread : Thread {

virtual void *thread_run()

io_thread.start();

thread safe

preemptive threading

context switch

event thread: causing the event thread to block for any length of time is considered bad programming practice. (unresponsive application)

Thread Synchronization

Monitors:

A monitor is a set of routines that are protected by a mutual exclusion lock.

A thread cannot execute any of the routines in the monitor until it acquires the lock, which means that only one thread at a time can execute within the monitor,
all other threads must wait for the currently executing thread to give up control of the lock.


Monitor is simpler to use.


Semaphores (mutex): A semaphore is a simpler construct, just a lock that protects a shared resource.

counting semaphores
event semaphore


Deadlock

Deadlock avoidance


Java:

public synchronized boolean deposit( double amount ) { }
public synchronized boolean withdraw( double amount) { }

or
synchronized(this) {


}

C#:

lock(this) {
.... //the code to protect, only within a method.
}


busy waiting

Java:

Thread task = new TheTask();

task.start();

while( task.isAlive() ) {
; // do nothing
}

Solution (shared object):

Object theLock = new Object(); //shared object

synchronized( theLock) {
Thread task = new TheTask( theLock );
task.start();


try {
theLock().wait();
}
catch (InterruptdException e) {
..... // do something if interrupted.
}
} //end of theLock


............

class TheTask extends Thread {

private Object theLock;

public TheTask( Object theLock) {
this.theLock = theLock;
}

public void run() {
synchronized ( theLock) {
....//do the task.
theLock.notify();
}
}
} //end of TheTask


///////////////////////////////////////////////////////
//The code can be simplified as:
///////////////////////////////////////////////////////

Thread task = new TheTask();
synchronized( task) {

task.start();

try {
task.wait();
}
catch ( InterruptedException e) {

.......//do something if interrupted
}

....................

class TheTask extends Thread {

public void run() {
synchronized( this ) {
.... // do the task.
this.notify();
}
}
} //end of TheTask


Producer/Consumer (java)

public class IntBuffer {

private int index;
private int[] buffer = new int[10];

public synchronized void add( int num ) {
while(index == buffer.length-1) {
try {
wait();
}
catch(InterruptedException e) {
}
} //end of while

buffer[index]=num; index++;
notifyAll();
}

public synchronized int remove() {
while(index == 0) {
try {
wait();
}
catch (InterruptedException e) {
}
} // end while

index --;
int ret = buffer[index];
notifyAll();
return(ret);

} //end of remove


} //end of class

public class Producer extends Thread {
private Intbuffer buffer;

public Producer( IntBuffer buffer) {
this.buffer = buffer;
}

public void run() {
Random r = new Random();
while(true) {
int num = r.nextInt();
buffer.add(num);
System.out.println("Produced " + num);
}
}
}


public class Consumer extends Thread {
private IntBuffer buffer;
public Consumer (IntBuffer buffer) {
this.buffer = buffer;
}

public void run() {
while (true) {
int num = buffer.remove();
System.out.println("Consumed " + num);
}
}
}


IntBuffer b = new IntBuffer();
Producer p = new Producer(b);
Consumer c = new Consumer(b);
p.start();
c.start();


The Dining Philosophers


public class DiningPhilosophers {

//each fork is just an Object we synchronize on
private Object[] forks;
private Philosopher[] philosophers;

private DiningPhilosophers (int num) {
forks = new Object[num];
philosophers = new philosopher[num];

for (int i = 0; i forks[i] = new Object();

int fork1 = i;
int fork2 = (i+1) % num;

if(i==0) //philosopher 0 picks up fork2 first.
philosophers[0] = new Philosopher( i, fork2, fork1 );
else

philosophers[i] = new Philosopher( i, fork1, fork2 );
}
}

public void startEating() throws InterruptedException {
for (int i =0; i < id="iv3o"> philosophers[i].start();
}

//suspend the main thread until the first philosopher stops eating, which will never happen
//this keeps the simulation running indefinitely

philosophers[0].join();
} //end startEating


private class Philosopher extends Thread {

private int id;
private int fork1;
private int fork2;

Philosopher (int id, int fork1, int fork2) {
this.id =id;
this.fork1 = fork1;
this.fork2 = fork2;
}

public void run() {

status("Ready to eat using forks "+fork1+ " and "+fork2);
pause(); //pause to let others get ready.

while(true) {
status("Picking up fork "+fork1);
synchronized ( forks[fork1]) {
status("Picking up fork "+fork2);
synchronized ( forks[fork2]) {
status("Eating");
} //fork2
} //fork1
} //while

} //end run

private void pause() {
try {
sleep(300);
}
catch ( InterruptedException e) {
//do nothing
}

}

private void status ( String msg) {
System.out.println("Philosopher " + id + ": " + msg);
}

} //end of philosopher

public static void main(String[] args) {
try {
DiningPhilosophers d = new DiningPhilosophers(5);
d.startEating();
}
catch ( InterruptedException e) {
}

} //end main

}


Multi-Threaded Programming With POSIX Threads(good tutorial)


Win32 Multithreaded Programming, Aaron Cohen and Mike Woodring, 1998
Errata and Source Code
Mike Woodring's .NET Sample Page

No comments: