在进行多线程编程时,难免还要碰到两个问题,那就线程间的互斥与同步:
线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。
线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模式下的方法有:事件,信号量,互斥量。
方法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();表示释放信号
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());
}
}
}
}方法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();
}
}
}
}- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
