Lectures‎ > ‎

Basic Threads

Overview

A thread is not an object, it's a series of executed instructions zipping thru method calls. Imagine multiple CPUs and each one running code in your program (same data space) at the same time like ants crawling all over a code printout. Java and the operating system take care of making one or a few CPUs handle many threads. Here is the way I think of two threads executing methods foo() and bar():





but in reality on single CPU:



Threads are useful because:
  • support concurrent operation. HTTP server. crontab system (restarts managers, does stats, etc...).
  • better system response. Add forum message; must add to search engine, email monitors.
  • exploit parallelism. dual server: supports simultaneous execution
  • Threads often permit simple programs. Sequential loop doing bits of this and that, but that is a scheduler. Don't have to check all the time for user events.

Launching threads

  1. Create class implementing Runnable.
  2. Define public void run() method. Thread dies when it exits.
  3. Elsewhere, create instance of class, a.
  4. Create new Thread(a), t, attached to a.
  5. t.start().
Do Jabber (like log server). Show lines of execution with interleaving.

class Jabber implements Runnable {
  String str;
  public Jabber(String s) { str = s; }
  public void run() { // thread dies when finished
    while (true) {
      System.out.print(str);
      System.out.println();
    }
  }
}

use via:

class JabberTest {
  public static void main(String[] args) {
    Jabber j = new Jabber("University of San Francisco");
    Jabber k = new Jabber("Computer Science 601");
    Thread t = new Thread(j);
    Thread u = new Thread(k);
    t.start();
    u.start();
  }
}

Thread control

  • join() wait for thread to finish
  • sleep(int n) sleep for n ms (keep locks)
  • interrupt() send signal to interrupt a sleeping or waiting thread
Computation c = new Computation(34);
Thread t = new Thread(c);
t.start();
t.join();
System.out.println("done");

Here is a modified Jabber that forces a yield every 5 prints:

public class Jabber implements Runnable {
    String str;
    int i = 0;
    public Jabber(String s) { str = s; }
    public void run() {
        while (true) {
            i++;
            if ( i%5==0 ) {
                Thread.yield();
            }
            System.out.print(str);
            System.out.println();
        }
    }
}

Auto yields when blocked on IO.

Synchronization, Interference

Shared resource example

"critical section": Trains on same track (semaphore term comes from this).

jGuru server pages: JSP share a single page object. Threads were stepping on the dynamic computations and output yielding bizarre stuff like the user name of one page would appear on somebody elses. I elected to have each page ref generate an object. GC can handle this pretty well. Plus I use a cache to avoid unnecessary computation.

<html>

<body>

<%! User u = getUser(); %> <!-- defines instance var -->

...

Hello <%= u.getName() %>!!!

</body>

</html>

Race condition example

Bank teller issue; get a student to be other teller. Ask them to look at board where you have $100 in account. Boss goes to other teller, you go to me as teller. Both want to add 5$. Race condition. No matter what, it's wrong value. "test and set" operations must be synchronized. Then note that if you record changes not new value: $100, +5$, +5% then it's ok. No test and set. So, sync reqts depend on what you are doing. Looks like

class Account {
  float balance = 0.0;
  public void deposit(float value) {
    balance = balance + value;
  }
}

Monitors

Java's thread model based upon monitors: chunks of data accessed only thru set of mutually exclusive accessor routines. We can this an object:

class Data {
      // ... elements ...
      public synchronized void insert(Object o) {...}
      public synchronized void delete(String key) {...}
      public synchronized void read(String key) {...}
}

synchronized method acquires a lock on the object (not the class).

Protects methods exec not data.

What happens when another thread interrupts and calls deposit? Solution:

class Account {
  float balance = 0.0;
  public synchronized void deposit(float value) {
    balance = balance + value;
  }
}

Like a "force field" around object.

Note: Can lock statements too with synchronized (object) statement.

Note: Class methods can be synchronized also:

class HPLaser {
  private static Device dev = ...;
  public static synchronized void print(String s) {...}
}

Note: Assignments are atomic minus long and double.

Note: local variables cannot be shared between threads so can't interfere.

Note: wait() (and notify) must happen in a synchronized block; sleep does not. Sleep()/yield() do not release the lock.

Java Memory Model

Jeremy Manson on volatile and java memory model

Synchronization Issues

Jeremy Manson on Double Checked Locking Issues and Double-checked locking:

// Correct multithreaded version
class Foo { 
  private Helper helper = null;

  public synchronized Helper getHelper() {
    if (helper == null) 
        helper = new Helper();
    return helper;
  }
  // other functions and members...
}
class Foo {
        private volatile Helper helper = null; // MUST be volatile

        public Helper getHelper() {
            if (helper == null) {
                synchronized(this) {
                    if (helper == null)
                        helper = new Helper(); // Helper init could happen out of order
                }
            }
            return helper;
        }
}


Thread locals

See TransactionIDs.java, EventMgr.java

Barriers

See ParallelCompute.java

AtomicIntegers


while ( true ) {
    int current = maxCount.get();
    int max = Math.max(current, n);
    if ( maxCount.compareAndSet(current, max) ) {
break;
    }
}

See ConcAtomInt.java

ConcurrentHashMap

See ConcMap.java
ċ
ConcAtomInt.java
(1k)
Terence Parr,
Sep 5, 2012, 2:00 PM
ċ
ConcMap.java
(1k)
Terence Parr,
Sep 5, 2012, 2:00 PM
ċ
EventMgr.java
(1k)
Terence Parr,
Aug 29, 2012, 2:03 PM
ċ
Jabber.java
(0k)
Terence Parr,
Aug 29, 2012, 2:03 PM
ċ
JabberTest.java
(0k)
Terence Parr,
Aug 29, 2012, 2:03 PM
ċ
ParallelCompute.java
(1k)
Terence Parr,
Aug 29, 2012, 2:03 PM
ċ
TransactionIDs.java
(1k)
Terence Parr,
Aug 29, 2012, 2:03 PM
Comments