线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。
线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模式下的方法有:事件,信号量,互斥量。
方法1:使用同步法,该方法的核心在于synchronized (lock) 其中lock必须是一个对象。
public class CriticalSectionSynchronizedBlock { static String message = "Now Is The Time For All Good Men\n"; static int numThreads = 200; static Integer lock = 1; public static void main(String args[]) { for (int idx = 0; idx < numThreads; idx++) { Thread t = new Thread(new StreamPrinter()); t.start(); } } static class StreamPrinter implements Runnable { @Override public void run() { while (true) { byte chars[] = message.getBytes(); synchronized (lock) { for (int idx = 0; idx < chars.length; idx++) { byte achar = chars[idx]; System.out.write((char) achar); Thread.yield(); } } } } } }
方法2: 使用信号灯:Semaphore(1)表示只能运行一个程序,Semaphore(n)可以运行n个线程
public class CriticalSectionSemaphore { static String message = "Now Is The Time For All Good Men\n"; static int numThreads = 200; public static void main(String args[]) { for (int idx = 0; idx < numThreads; idx++) { Thread t = new Thread(new StreamPrinter()); t.start(); } } static class StreamPrinter implements Runnable { static Semaphore sema = new Semaphore(1); @Override public void run() { try { while (true) { byte chars[] = message.getBytes(); sema.acquire(); for (int idx = 0; idx < chars.length; idx++) { byte achar = chars[idx]; System.out.write((char) achar); Thread.yield(); } sema.release(); } } catch (InterruptedException ex) { System.err.println(ex.getLocalizedMessage()); } } } }
acquire();表示获取信号 release();表示释放信号
1: public class CriticalSectionMonitor
2: {
3: static String message = "Now Is The Time For All Good Men\n";
4: static int numThreads = 200;
5: static Object monitor = new Object();
6: public static void main(String args[])
7: {
8: for (int idx = 0; idx < numThreads; idx++) {
9: Thread t = new Thread(new StreamPrinter());
10: t.start();
11: }
12: // Needed to start / unblock the first waiting thread.
13: synchronized(monitor) {
14: monitor.notify();
15: }
16: }
17: static class StreamPrinter implements Runnable
18: {
19: @Override
20: public void run()
21: {
22: try {
23: while (true) {
24: byte chars[] = message.getBytes();
25: synchronized(monitor) { // Start Critical Section
26: monitor.wait();
27: }
28: for (int idx = 0; idx < chars.length; idx++) {
29: byte achar = chars[idx];
30: System.out.write((char) achar);
31: Thread.yield();
32: }
33: synchronized(monitor) { // End Critical Section
34: monitor.notify();
35: }
36: }
37: }
38: catch (InterruptedException ex) {
39: System.err.println(ex.getLocalizedMessage());
40: }
41: }
42: }
43: }
方法3:monitor
- public class CriticalSectionMonitor
- {
- static String message = "Now Is The Time For All Good Men\n";
- static int numThreads = 200;
- static Object monitor = new Object();
- public static void main(String args[])
- {
- for (int idx = 0; idx < numThreads; idx++) {
- Thread t = new Thread(new StreamPrinter());
- t.start();
- }
- // Needed to start / unblock the first waiting thread.
- synchronized(monitor) {
- monitor.notify();
- }
- }
- static class StreamPrinter implements Runnable
- {
- @Override
- public void run()
- {
- try {
- while (true) {
- byte chars[] = message.getBytes();
- synchronized(monitor) { // Start Critical Section
- monitor.wait();
- }
- for (int idx = 0; idx < chars.length; idx++) {
- byte achar = chars[idx];
- System.out.write((char) achar);
- Thread.yield();
- }
- synchronized(monitor) { // End Critical Section
- monitor.notify();
- }
- }
- }
- catch (InterruptedException ex) {
- System.err.println(ex.getLocalizedMessage());
- }
- }
- }
- }
注意下面两个例子中的错误,第一个是是没有同步方法,第二个是同步错误,该class使用同步方法,但是没有静态化,所以200个线程只是锁定了自己的方法,同步没有达到该有的效果。
- public class CriticalSectionBroken
- {
- static String message = "Now Is The Time For All Good Men\n";
- static int numThreads = 200;
- public static void main(String args[])
- {
- for (int idx = 0; idx < numThreads; idx++) {
- Thread t = new Thread(new StreamPrinter());
- t.start();
- }
- }
- static class StreamPrinter implements Runnable
- {
- @Override
- public void run()
- {
- while (true) {
- byte chars[] = message.getBytes();
- for (int idx = 0; idx < chars.length; idx++) {
- byte achar = chars[idx];
- System.out.write((char) achar);
- Thread.yield();
- }
- }
- }
- }
- }
- public class CriticalSectionFailedSynchronize
- {
- static String message = "Now Is The Time For All Good Men\n";
- static int numThreads = 200;
- public static void main(String args[])
- {
- for (int idx = 0; idx < numThreads; idx++) {
- Thread t = new Thread(new StreamPrinter());
- t.start();
- }
- }
- static class StreamPrinter implements Runnable
- {
- @Override
- public void run()
- {
- while (true) {
- printMessage();
- }
- }
- private synchronized void printMessage()
- {
- byte chars[] = message.getBytes();
- for (int idx = 0; idx < chars.length; idx++) {
- byte achar = chars[idx];
- System.out.write((char) achar);
- Thread.yield();
- }
- }
- }
- }
No comments:
Post a Comment