Java 多线程同步并发问题
以车站多窗口售票为例:
窗口程序代码:
public class ticket extends Thread{
int num=20;
public ticket(String name){
super(name);
}
public void run(){
while (num > 0) {
//synchronized(this) {
System.out.println(“当前余票:” + num + Thread.currentThread().getName() + “正在卖票”);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num–;
}
if (num <= 0) {
System.out.println(“余票不足”);
}
//}
}
}
多线程代码:
public class ticketMain {
public static void main(String[] args){
//ticket t=new ticket();
ticket t1=new ticket(“窗口1”);
ticket t2=new ticket(“窗口2”);
ticket t3=new ticket(“窗口3”);
ticket t4=new ticket(“窗口4”);
// Thread t1=new Thread(t,“窗口1”);
// Thread t2=new Thread(t,“窗口2”);
// Thread t3=new Thread(t,“窗口3”);
// Thread t4=new Thread(t,“窗口4”);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
你会发现这个时候多个线程操作同一个成员变量的时候,数据会出现异常,不能实现数据的同步。
原因:当多条语句在同时操作一个线程共享数据时,一个线程对多条语句只执行了一部分,另外一个线程来参与执行时,导致共享数据的错误
解决方法:对多条操作共享数据的语句需要某个时间段内只允许一条线程执行。执行过程中,其他线程不允许参与。也即是:同步代码块
同步代码块object锁:
synchronized(对象){
不可拆分的代码块
}
修改后的代码:
窗口代码:
public class ticket implements Runnable{
int num=20;
// public ticket(String name){
// super(name);
// }
public void run(){
while (num > 0) {
synchronized(this) {
System.out.println(“当前余票:” + num + Thread.currentThread().getName() + “正在卖票”);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num–;
}
}
if (num <= 0) {
System.out.println(“余票不足”);
}
}
}
多线程代码:
public class ticketMain {
public static void main(String[] args){
ticket t=new ticket();
// ticket t1=new ticket(“窗口1”);
// ticket t2=new ticket(“窗口2”);
// ticket t3=new ticket(“窗口3”);
// ticket t4=new ticket(“窗口4”);
Thread t1=new Thread(t,“窗口1”);
Thread t2=new Thread(t,“窗口2”);
Thread t3=new Thread(t,“窗口3”);
Thread t4=new Thread(t,“窗口4”);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
程序分析:
这里相对于之前使用了Runnable实现多线程,具有以下优势:
1:适合多个相同的程序代码块的线程去处理同一个资源。
2: 可以避免java中单继承的限制。
增加程序块的健壮性,代码可以被多个线程共享,代码和数据独立。
使用同步代码块的前提是:必须有两个或者多个线程,必须是多个线程使用同一把锁。
好处:解决线程的安全问题。
坏处:多线程需要判断锁,执行效率降低。