publicstaticvoid main(String[] args) {
//show2();
show();
}
publicstaticvoid show(){
Appleap=newApple("ljf1");
Thread t1=new Thread(ap);
Thread t2=new Thread(ap);
Thread t3=new Thread(ap);
Thread t4=new Thread(ap);
t1.start();
t2.start();
t3.start();
t4.start();
}
publicclass Appleimplements Runnable{
private Stringname;
public Apple(String name){
this.name=name;
}
privateintticket=100;
publicvoid run(){
while(ticket>0){
try { //A,b,c,d,当A线程的ticket=1,判断之后合法,进入执行sleeep,b的ticket此时也=1,
//然后执行sleep,A获得执行权,进行了ticket--,此时为0,b此时或得执行权,ticket--,后ticket为-1,出现不合法的情况。
Thread.sleep(10);
} catch (InterruptedException e) {
//TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println("name:"+name+":"+(ticket--));
}
}
}
截取部分结果:
name:ljf1:16
name:ljf1:15
name:ljf1:14
name:ljf1:13
name:ljf1:12
name:ljf1:11
name:ljf1:10
name:ljf1:9
name:ljf1:8
name:ljf1:7
name:ljf1:6
name:ljf1:5
name:ljf1:4
name:ljf1:3
name:ljf1:2
name:ljf1:1
name:ljf1:0
name:ljf1:-1
name:ljf1:-2
1原因:多条语句来操作同一线程的共享资源时,一个线程对多条语句只执行了一部分,还没有执行完,另外一个线程参与来执行,导致共享资源的错误。
解决的办法:使用同步代码块。
解决的办法:使用同步代码块。
Synchronized(同步对象){
需要被同步的代码块。
}
加锁修改之后:
publicclass Appleimplements Runnable{
private Stringname;
public Apple(String name){
this.name=name;
}
privateintticket=100;
Objectobj=newObject();
publicvoid run(){
synchronized(obj){
while(ticket>0){
try { //A,b,c,d,当A线程的ticket=1,判断之后合法,进入执行sleeep,b的ticket此时也=1,
//然后执行sleep,A获得执行权,进行了ticket--,此时为0,b此时或得执行权,ticket--,后ticket为-1,出现不合法的情况。
Thread.sleep(10);
} catch (InterruptedException e) {
//TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println("name:"+name+":"+(ticket--));
}
}
}
}
总结:对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取cpu的执行权也进不去。
同步的前提:1.必须要有两个或者两个以上的线程。2必须是多个线程使用同一个锁。必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
2.
第二种方式:使用同步函数:函数都需要被对象调用,函数都有一个所属对象的引用,this
同步函数所使用的锁是this;
public static void main(String[] args) {
Apple apple=new Apple("ljf");
new Thread(apple).start();
new Thread(apple).start();
new Thread(apple).start();
new Thread(apple).start();
}
public class Apple implements Runnable{
private int ticket=100;
private String name;
public Apple(String name) {
super();
this.name=name;
}
public void run(){
while(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+">>"+ticket--);
}
}
}
出现不和谐的情况:
ljf>>100
.
.
.
ljf>>12
ljf>>11
ljf>>13
ljf>>10
ljf>>9
ljf>>8
ljf>>7
ljf>>6
ljf>>5
ljf>>2
ljf>>3
ljf>>4
ljf>>1
ljf>>-2
ljf>>-1
ljf>>0
给方法加上同步修饰符,使其变为同步函数:
public class Apple implements Runnable{
private int ticket=100;
private String name;
public Apple(String name) {
super();
this.name=name;
}
public synchronized void run(){
while(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+">>"+ticket--);
}
}
结果为:
.
.
.
ljf>>9
ljf>>8
ljf>>7
ljf>>6
ljf>>5
ljf>>4
ljf>>3
ljf>>2
ljf>>1