public class test{
public static void main(String[] args) throws IOException{
Thread1 t1 = new Thread1("A");
Thread1 t2 = new Thread1("B");
Thread1 t3 = new Thread1("C");
t1.start();
t2.start();
t3.start();
}
}class Thread1 extends Thread{
private static int num = 50;
public Thread1(String string){
super(string);
}
@Override
public void run(){
for(int i=0;i<50;i++){
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(num>0){
System.out.println(this.currentThread().getName()+">>>>>"+(--num));
}
}
}
}C>>>>>48
A>>>>>48//出现重复数字
B>>>>>49
A>>>>>47
B>>>>>47
C>>>>>46
B>>>>>45
C>>>>>44
A>>>>>45
B>>>>>42
C>>>>>42
A>>>>>43
C>>>>>41
B>>>>>41
A>>>>>41
B>>>>>40
C>>>>>40
A>>>>>40
B>>>>>39
A>>>>>39
C>>>>>39
A>>>>>38
B>>>>>38
C>>>>>38
C>>>>>37
B>>>>>36
A>>>>>37
A>>>>>35
C>>>>>33
B>>>>>34
C>>>>>32
A>>>>>31
B>>>>>30
C>>>>>29
A>>>>>29
B>>>>>29
A>>>>>28
C>>>>>28
B>>>>>27
C>>>>>26
A>>>>>26
B>>>>>26
A>>>>>25
C>>>>>24
B>>>>>25
B>>>>>23
C>>>>>22
A>>>>>23
C>>>>>21
A>>>>>21
B>>>>>20
C>>>>>19
A>>>>>19
B>>>>>19
B>>>>>18
A>>>>>17
C>>>>>16
C>>>>>15
B>>>>>13
A>>>>>14
C>>>>>12
A>>>>>11
B>>>>>12
A>>>>>10
C>>>>>10
B>>>>>10
A>>>>>9
C>>>>>8
B>>>>>8
B>>>>>7
A>>>>>5
C>>>>>6
A>>>>>4
B>>>>>4
C>>>>>4
B>>>>>2
C>>>>>1
A>>>>>3
A>>>>>0
C>>>>>-1//出现负数
B>>>>>0原因:当两个线程同时进入到if(num>0)的代码块中,一个线程开始执行输出语句,但还没执行到--num,另一条线程也开始执行打印操作,就会打印相同的数字。同样,当一条线程执行完--num且num=0,就会出现另一条线程执行完--num出现的是-1。
解决办法:
- 使用同步代码块
public void run(){
for(int i=0;i<50;i++){
//使用同步代码块
synchronized(this.getClass()){
if(num>0){
···
}
}
}
}语法:
synchronized(同步锁){
//需要同步操作的代码(最多只有一个线程能够拿到同步锁,拿到同步锁之后该线程才能进入代码块)
}- 使用同步方法
使用synchronized关键字来修饰方法
@Override
public void run(){
for(int i=0;i<50;i++){
sell();
}
}
private synchronized void sell(){
if(num>0){
···
}
}注意:不能用synchronized来修饰run()方法,不然只能有一个线程进去执行完所有的操作。
- 使用锁机制
public class test{
public static void main(String[] args) throws IOException{
Lock l = new ReentrantLock();
Thread1 t1 = new Thread1("A",l);
Thread1 t2 = new Thread1("B",l);
Thread1 t3 = new Thread1("C",l);
t1.start();
t2.start();
t3.start();
}
}
class Thread1 extends Thread{
String name;
Lock lock;
private static int num = 50;
public Thread1(String string,Lock lock) {
this.name = string;
this.lock = lock;
}
@Override
public void run(){
for(int i=0;i<50;i++){
lock.lock();
try {
if(num>0){
sleep(10);
System.out.println(this.currentThread().getName()+">>>>>"+(--num));
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
lock.unlock();
}
}
}
}注意:要把锁作为参数给每一个线程。

本文通过一个Java多线程示例程序展示了由于线程间未进行有效同步而导致的数据竞争问题,并提供了三种解决方案:使用synchronized关键字创建同步代码块、使用synchronized方法以及采用显式的锁机制。

被折叠的 条评论
为什么被折叠?



