基本上所有解决多线程资源冲突问题的方法都是采用给定时间只允许一个线程访问共享资源,这时就需要给共享资源上一道锁。

Java中提供了同步机制,可以有效地防止资源冲突。同步机制使用synchronized关键字。

同步块

synchronized(Object){

}

注意在初始化Object对象时,不要将其定义在run()方法中,应该将其定义在run()方法外(看代码案例)。

通常将共享资源的操作放置在synchronized定义的区域内,这样当其他线程也获取到这个锁时,必须等待锁被释放才能进入该区域。

Object为任意对象,每个对象都存在一个标志位,并具有两个值:0和1。一个线程运行到同步块时首先检查该对象的标志位,如果为0的状态,表明此同步块中存在其他线程运行,这时该线程处于就绪状态,直到处于同步块中的线程执行完同步块中的代码为止,这时该对象的标志位被设置为1,该线程才能执行同步块中的代码,并将Object对象的标志位设置为0,防止其他线程执行同步块中的代码。

(0表示有线程正在使用该同步块,1表示没有线程正在使用该同步块。

一个线程运行到同步块时先检查Object对象是否为0,若为0则等待其他线程执行完该同步块在执行;若为1则执行该同步块,并Object设对象置为0,防止其他线程执行该同步块,执行完事之后再释放该同步块,方便其他线程执行。)

import java.util.*;

public class t4 {

public static void main(String[] args) {
// TODO Auto-generated method stub
C my = new C();
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
Thread t3 = new Thread(my);

t1.start();
t2.start();
t3.start();

}

}

class C implements Runnable{

int count = 10;
Object lock = new Object(); //lock锁一定要定义在这里,不能定义在run方法中,run方法是线程调用方法

@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
synchronized(lock){
if(count != 0) {
try {
Thread.sleep(100);
}catch(Exception e) {
e.printStackTrace();
}

System.out.println(count--);
}else {
break;//停止循环体
}
}
}


}

}

运行结果是:按照顺序输出10,9,8,7,6,5,4,3,2,1

同步方法

同步方法就是在方法前面加修饰synchronized关键字的方法

例如:synchronized void test( ){ }

运行机制与同步块机制一样

import java.util.*;

public class t4 {

public static void main(String[] args) {
// TODO Auto-generated method stub
C my = new C();
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
Thread t3 = new Thread(my);

t1.start();
t2.start();
t3.start();

}

}

class C implements Runnable{
int count = 10;

public synchronized void test() {
while(true) {
if(count != 0) {
try {
Thread.sleep(100);
}catch(Exception e) {
e.printStackTrace();
}

System.out.println(count--);
}else {
break;//停止循环体
}
}

}

@Override
public void run() {
// TODO Auto-generated method stub
test();
}

}

运行结果是:按照顺序输出10,9,8,7,6,5,4,3,2,1