public class Lesson5TestDemo1
{
public static void main(String [] args)
{
Lesson5TestDemo2 rr = new Lesson5TestDemo2();
new Thread(rr).start();
new Thread(rr).start();
new Thread(rr).start();
new Thread(rr).start();
}
}
//这是卖票
class Lesson5TestDemo2 implements Runnable
{
private int tickets = 100;
//private String str = new String("");
public void run()
{
while(true)
{
//synchronized必须要锁定一个对象,注意是对象,基本类型的数据是不行的,至于锁定什么对象,随便你
/*
*synchronized的工作原理:当我们有一个线程运行到这个synchronized锁定的代码块里面的时候,
* 这时候就会设置一个标志,(其实这个标志就是加上锁),当加锁上以后,那么只有等待这个线程运行
*完,运行完后就会释放这个锁,让其他的线程来运行
*
*
*/
//但是一旦加上同步锁定器,我们的程序会慢些,因为我们需要随时来监听这个对象是否加上锁,这是需要消耗
//性能,也就是以性能换取安全性,如果我们的数据没有涉及到安全的问题,不要轻易使用synchronized
//String str = new String("");//千万不要把这个锁定的对象放到run方法里面,因为一旦放到run方法里面
//建立的四个线程,其实每次锁定的对象都不是同一个对象,那么依然会出现问题
//这是代码块的同步
/*<1>:这样做极有可能会出现线程安全的问题,当我们有一个线程A运行到打印出我们的sys语句的时候,
*假设打印出来5,这时候运行到另外一个线程B,此时判断5大于0,
*当线程B运行到我们的sys的打印语句的时候,打印出5,又回到先前的线程A
*在线程A里面,tickets--变成了4,然后又回到线程B里面,执行tickets--变成了3,
*那么在这个过程中我们的tickets为4就永远不会出现,
*<2>:还是上面这种情况,加入我们的初始值是1,那么我们就会出现tickets为-1的情况
*为了解决这种情况,我们就用到了synchronized这个关键字
*/
/*synchronized(str)
{
if(tickets > 0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+" is saling the ticket of " + tickets--);
}
}*/
//这是用函数同步来解决这个问题
while(true)
{
sale();
}
}
}
//这是函数同步的代码,其实函数同步也是用锁定一个对象来实现的同步,它锁定的就是this
public synchronized void sale()
{
if(tickets > 0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+" is saling the ticket of " + tickets--);
}
}
}