Contents

  1. .
  2. ./BoundedBuffer.java
  3. ./CriticalSectionEx.java
  4. ./index.html
  5. ./SerializationExCond.java
  6. ./SerializationEx.java
  7. ./SerializationExSem.java
  8. ./SodaMachineWithConditionVariable.java
  9. ./SodaMachineWithSemaphore.java

. 1/9

[
top][prev][next]


./BoundedBuffer.java 2/9

[
top][prev][next]

import java.util.concurrent.*;
import java.util.concurrent.locks.*;

/**
 * Adapted from https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html
 * 
 * @author CSCI330
 */
class BoundedBuffer {
	final Lock lock = new ReentrantLock();
	/** the buffer is not full. 
	Consumer signals when it has taken something from the buffer, 
	so the buffer is not full. */
	final Condition notFull = lock.newCondition();
	/** the buffer is not empty.  
	Producer signals when it has put something in the buffer, so the buffer is not empty. */
	final Condition notEmpty = lock.newCondition();
	
	final Object[] items = new Object[100];
	private int putptr, takeptr, count;
	
	public static void main(String args[]) {
	     BoundedBuffer bbuf = new BoundedBuffer();
	     Thread producer = new Producer(bbuf);
	     Thread consumer = new Consumer(bbuf);
	     
	     producer.start();
	     consumer.start();
	}

	/**
	 * If the buffer is full, can't put any items.
	 */
	public void put(Object x) throws InterruptedException {
		lock.lock();
		try {
			while (count == items.length)
				notFull.await();
			items[putptr] = x;
			if (++putptr == items.length) // wrap pointer around
				putptr = 0;
			count++;
			notEmpty.signal();
		} finally {
			lock.unlock();
		}
	}

	/**
	 * If take is attempted on an empty buffer, wait
	 */ 
	public Object take() throws InterruptedException {
		lock.lock();
		try {
			while (count == 0)
				notEmpty.await();
			Object x = items[takeptr];
			if (++takeptr == items.length) // wrap pointer around
				takeptr = 0;
			count--;
			notFull.signal();
			return x;
		} finally {
			lock.unlock();
		}
	}
}

class Producer extends Thread {
    
    private BoundedBuffer bb;
    
    public Producer( BoundedBuffer bb ) {
        this.bb = bb;   
    }
    
    public void run() {
        Integer num = 0;
        while( true ) {
            try {
                bb.put(num);
            } catch(InterruptedException exc ) {
                exc.printStackTrace();   
            }
            num ++;
            if( num == 10 ) {
                yield();
                num = 0;
            }
        }
    }
    
}

class Consumer extends Thread {
    
    private BoundedBuffer bb;
    
    public Consumer( BoundedBuffer bb ) {
        this.bb = bb;   
    }
 
    public void run() {
        Object o = null;
        while( true ) {
            try {
                 o = bb.take(); 
            } catch(InterruptedException exc ) {
                exc.printStackTrace();   
            }
            System.out.println("read: " + o);
        }
    }
    
}

./CriticalSectionEx.java 3/9

[
top][prev][next]
/**
 * A motivating example for thread synchronization -- mutual exclusion problem.
 * 
 * Periodically prints x[0], while two threads are increasing or decreasing,
 * respectively, its value.  
 *
 * @author Grant Braught
 *
 */
public class CriticalSectionEx {

    public static void main(String[] args) {

        for (int i = 1; i <= 100; i++) {
            Integer[] x = { new Integer(0) };

            Thread threadInc = new IncThread(x);
            Thread threadDec = new DecThread(x);

            threadInc.start();
            threadDec.start();

            try {
                threadInc.join();
                threadDec.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.print(x[0] + "\t");
            if (i % 10 == 0) {
                System.out.println();
            }
        }
    }
}

/*
 * Increases x[0] by 1, 500,000
 */
class IncThread extends Thread {

    private Integer[] x;

    public IncThread(Integer[] x) {
        this.x = x;
    }

    public void run() {
        for (int i = 0; i < 500000; i++) {
            x[0] = new Integer(x[0] + 1);
        }
    }
}

/*
 * Decreases x[0] by 1, 500,000 times
 */
class DecThread extends Thread {

    private Integer[] x;

    public DecThread(Integer[] x) {
        this.x = x;
    }

    public void run() {
        for (int i = 0; i < 500000; i++) {
            x[0] = new Integer(x[0] - 1);
        }
    }
}

./index.html 4/9

[
top][prev][next]
<html>
<head><title>Examples for /home/faculty/sprenkle/public_html/cs330/examples/23-java_synchronization</title>
<link rel="stylesheet" type="text/css" href="http://www.cs.wlu.edu/~sprenkle/cs330/css/themes/spacelab.min.css" />
<link rel="stylesheet" type="text/css" href="http://www.cs.wlu.edu/~sprenkle/cs330/css/course.css" />
<link rel="stylesheet" type="text/css" href="http://www.cs.wlu.edu/~sprenkle/cs330/css/syntax.css" />
<link rel="stylesheet" type="text/css" href="http://www.cs.wlu.edu/~sprenkle/cs330/css/style.css" />
</head>
<body>
<h1>Examples for /home/faculty/sprenkle/public_html/cs330/examples/23-java_synchronization</h1>
<ul>
<li><a href=".//code.html">All IN ONE FILE (pretty syntax)</a>
<li><a href=".//BoundedBuffer.java">BoundedBuffer.java</a></li>
<li><a href=".//CriticalSectionEx.java">CriticalSectionEx.java</a></li>
<li><a href=".//SerializationEx.java">SerializationEx.java</a></li>
<li><a href=".//SerializationExCond.java">SerializationExCond.java</a></li>
<li><a href=".//SerializationExSem.java">SerializationExSem.java</a></li>
<li><a href=".//SodaMachineWithConditionVariable.java">SodaMachineWithConditionVariable.java</a></li>
<li><a href=".//SodaMachineWithSemaphore.java">SodaMachineWithSemaphore.java</a></li>
</ul>
</body>

./SerializationExCond.java 5/9

[
top][prev][next]
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A solution using condition variables
 * 
 * @author Grant Braught
 * @author CSCI330
 */
public class SerializationExCond {

	public static Lock myLock = new ReentrantLock();
	public static Condition notDone = myLock.newCondition();
	public static boolean done;

	public static void main(String[] args) {

		for (int i = 1; i <= 100; i++) {
			int[] x = { 1, 0 };

			Thread threadA = new ThreadACond(x);
			Thread threadB = new ThreadBCond(x);

			done = false;
			threadA.start();
			threadB.start();

			try {
				threadA.join();
				threadB.join();
			} catch (InterruptedException e) {
			}

			if (i % 10 == 0) {
				System.out.println();
			} else {
				System.out.print("\t");
			}
		}
	}
}

class ThreadACond extends Thread {

	private int[] x;

	public ThreadACond(int[] x) {
		this.x = x;
	}

	public void run() {
		doWork();
		SerializationExCond.myLock.lock();
		x[0] = 5;
		doWork();
		System.out.print(x[0] + " ");
		SerializationExCond.done = true;
		SerializationExCond.notDone.signal();
		SerializationExCond.myLock.unlock();
	}

	public void doWork() {
		for (int i = 0; i < 100000; i++) {
			new Double(Math.random());
		}
	}
}

class ThreadBCond extends Thread {

	private int[] x;

	public ThreadBCond(int[] x) {
		this.x = x;
	}

	public void run() {
		doWork();
		SerializationExCond.myLock.lock();
		while (!SerializationExCond.done) {
			try {
				SerializationExCond.notDone.await();
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
		x[1] = x[0] + 3;
		doWork();
		System.out.print(x[1] + " ");
		SerializationExCond.myLock.unlock();
	}

	public void doWork() {
		for (int i = 0; i < 100000; i++) {
			new Double(Math.random());
		}
	}
}

./SerializationEx.java 6/9

[
top][prev][next]
/**
 * A motivating example for thread serialization
 * -- want the threads to alternate -- 
 * not execute at the same time.
 * 
 * @author Grant Braught
 */
public class SerializationEx {

	public static void main(String[] args) {

		for (int i = 1; i <= 100; i++) {
			int[] x = { 1, 0 };

			Thread ta = new ThreadA(x);
			Thread tb = new ThreadB(x);

			ta.start();
			tb.start();

			try {
				ta.join();
				tb.join();
			} catch (InterruptedException e) {
			}

			if (i % 10 == 0) {
				System.out.println();
			} else {
				System.out.print("\t");
			}
		}
	}
}

class ThreadA extends Thread {

	private int[] x;

	public ThreadA(int[] x) {
		this.x = x;
	}

	public void run() {
		doWork();
		x[0] = 5;
		doWork();
		System.out.print(x[0] + " ");
	}

	public void doWork() {
		for (int i = 0; i < 100000; i++) {
			new Double(Math.random());
		}
	}
}

class ThreadB extends Thread {

	private int[] x;

	public ThreadB(int[] x) {
		this.x = x;
	}

	public void run() {
		doWork();
		x[1] = x[0] + 3;
		doWork();
		System.out.print(x[1] + " ");
	}

	public void doWork() {
		for (int i = 0; i < 100000; i++) {
			new Double(Math.random());
		}
	}
}

./SerializationExSem.java 7/9

[
top][prev][next]
import java.util.concurrent.*;

/**
 * Alternate between ThreadA and ThreadB, displaying
 * 5 (from ThreadA) and 8 (from ThreadB) in 10 columns, and 10 rows
 * 
 * @author Grant Braught
 * @author CSCI330
 */
public class SerializationExSem {

	public static Semaphore aSem = new Semaphore(1);
	public static Semaphore bSem = new Semaphore(0);

	public static void main(String[] args) {

		for (int i = 1; i <= 100; i++) {
			int[] x = { 1, 0 };

			Thread threadA = new ThreadASem(x);
			Thread threadB = new ThreadBSem(x);

			threadA.start();
			threadB.start();

			try {
			    // wait for the threads to finish
				threadA.join();
				threadB.join();
			} catch (InterruptedException e) {
			    e.printStackTrace();
			}

			if (i % 10 == 0) {
			    // print a new line every 10 times
				System.out.println();
			} else {
			    // usually, print a tab
				System.out.print("\t");
			}
		}
	}
}

/**
 * Sets x[0] = 5 and displays it
 */
class ThreadASem extends Thread {

	private int[] x;

	public ThreadASem(int[] x) {
		this.x = x;
	}

	public void run() {
		doWork();
		try {
			SerializationExSem.aSem.acquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		x[0] = 5;
		doWork();
		System.out.print(x[0] + " ");
		SerializationExSem.bSem.release();
	}

	public void doWork() {
		for (int i = 0; i < 100000; i++) {
			new Double(Math.random());
		}
	}
}

/**
 * Sets x[1] to x[0] + 3 and displays x[1]
 */
class ThreadBSem extends Thread {

	private int[] x;

	public ThreadBSem(int[] x) {
		this.x = x;
	}

	public void run() {
		doWork();
		try {
			SerializationExSem.bSem.acquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		x[1] = x[0] + 3;
		doWork();
		System.out.print(x[1] + " ");
		SerializationExSem.aSem.release();
	}

	public void doWork() {
		for (int i = 0; i < 100000; i++) {
			new Double(Math.random());
		}
	}
}

./SodaMachineWithConditionVariable.java 8/9

[
top][prev][next]

import java.util.concurrent.locks.*;

/**
 * Another example of a producer-consumer problem:
 * this time, a SodaMachine, using condition variables
 * 
 * @author CSCI330
 */
class SodaMachineWithConditionVariable {
    
    /* Shared State */
    // made this kinda large, so you can better see the switching between threads
    public static int maxSodas = 100; 
    public static int numSodas = 0;
    // could also have a soda buffer
    
    /* Synchronization Tools */
    /** lock to update shared state */
	public static final Lock sodaLock = new ReentrantLock();
	/** the soda machine has space; producer can produce; 
	consumer notifies when takes a soda */
	public static final Condition hasRoom = sodaLock.newCondition();
	/** the soda machine has soda; consumer can consume; 
	producer notifies when adds a soda */
	public static final Condition hasSoda = sodaLock.newCondition();
	
	public static void main(String args[]) {
	     Thread producer = new SodaProducer(1);
	     Thread producer2 = new SodaProducer(2);

	     // can run with fewer producer/consumers.  This just helps illustrate
	     // better what's happening with multiple threads.
	     Thread consumer = new SodaConsumer(1);
	     Thread consumer2 = new SodaConsumer(2);
	     
	     producer.start();
	     consumer.start();
	     producer2.start();
	     consumer2.start();
	}

}

class SodaProducer extends Thread {
    private int id;
    public SodaProducer( int id ) { this.id = id;}
    
    public void run() {
        while( true ) {
            SodaMachineWithConditionVariable.sodaLock.lock();
    
            while(SodaMachineWithConditionVariable.numSodas==SodaMachineWithConditionVariable.maxSodas){
                try {
                    SodaMachineWithConditionVariable.hasRoom.await();
                } catch( Exception e ) {
                    e.printStackTrace();
                }
            }
    
            SodaMachineWithConditionVariable.numSodas++;
            System.out.println(id + ": Adding a soda: " + SodaMachineWithConditionVariable.numSodas);
            
            SodaMachineWithConditionVariable.hasSoda.signal();
    
            SodaMachineWithConditionVariable.sodaLock.unlock();
        }
    }
    
}

class SodaConsumer extends Thread {
    private int id;
    public SodaConsumer(int id) { this.id = id;  }
 
    public void run() {
        while( true ) {
            SodaMachineWithConditionVariable.sodaLock.lock();
            
            while (SodaMachineWithConditionVariable.numSodas == 0) {
                try {
                    SodaMachineWithConditionVariable.hasSoda.await();
                } catch( Exception e ) {
                    e.printStackTrace();
                }
            }
            
            SodaMachineWithConditionVariable.numSodas--;
            System.out.println(id + ": Remove a soda: " + SodaMachineWithConditionVariable.numSodas);
            SodaMachineWithConditionVariable.hasRoom.signal();
            
            SodaMachineWithConditionVariable.sodaLock.unlock();
        }
    }
}

./SodaMachineWithSemaphore.java 9/9

[
top][prev][next]
import java.util.concurrent.*;

/**
 * Another example of a producer-consumer problem: 
 * this time, a SodaMachine, using semaphores
 * 
 * @author CSCI330
 */
class SodaMachineWithSemaphore {
    
    /* Shared State */
    // made this kinda large, so you can better see the switching between threads
    public static int maxSodas = 2; 
    public static int numSodas = 0;
    // could also have a soda buffer
    
    /* Synchronization Tools */
    /** lock to update shared state */
	public static final Semaphore sodaLock = new Semaphore(1);
	/** the soda machine has space; producer decrements -- if 0, waits to produce; consumer increments 
	 */
	public static final Semaphore emptySlots = new Semaphore(maxSodas);
	/** the soda machine has soda; consumer decrements -- if 0, waits to consumer; producer increments */
	public static final Semaphore fullSlots = new Semaphore(0);
	
	public static void main(String args[]) {
	     Thread producer = new SodaProducerSem(1);
	     Thread producer2 = new SodaProducerSem(2);

	     // can run with fewer producer/consumers.  This just helps illustrate
	     // better what's happening with multiple threads.
	     Thread consumer = new SodaConsumerSem(1);
	     Thread consumer2 = new SodaConsumerSem(2);
	     
	     producer.start();
	     consumer.start();
	     producer2.start();
	     consumer2.start();
	}

}

class SodaProducerSem extends Thread {
    private int id;
    public SodaProducerSem( int id ) { this.id = id;}
    
    public void run() {
        while( true ) {
            try {
                SodaMachineWithSemaphore.emptySlots.acquire();
                SodaMachineWithSemaphore.sodaLock.acquire();
            } catch( InterruptedException e ) {
                e.printStackTrace();   
            }
            
            // the assert condition should never be true. 
            // checking because no explicit condition, 
            // as in condition variable solution
            assert SodaMachineWithSemaphore.numSodas < SodaMachineWithSemaphore.maxSodas;
            SodaMachineWithSemaphore.numSodas++;
            System.out.println(id + ": Adding a soda: " + SodaMachineWithSemaphore.numSodas);
            
            SodaMachineWithSemaphore.sodaLock.release();
            
            SodaMachineWithSemaphore.fullSlots.release();
        }
    }
    
}

class SodaConsumerSem extends Thread {
    private int id;
    public SodaConsumerSem(int id) { this.id = id;  }
 
    public void run() {
        while( true ) {
            try {
                SodaMachineWithSemaphore.fullSlots.acquire();
                SodaMachineWithSemaphore.sodaLock.acquire();
            } catch( InterruptedException e ) {
                e.printStackTrace();   
            }
            // the assert condition should never be true
            assert SodaMachineWithSemaphore.numSodas > 0;
            SodaMachineWithSemaphore.numSodas--;
            System.out.println(id + ": Remove a soda: " + SodaMachineWithSemaphore.numSodas);
            
            SodaMachineWithSemaphore.sodaLock.release();
            
            SodaMachineWithSemaphore.emptySlots.release();
        }
    }
}

Generated by GNU Enscript 1.6.6.