线程同步
买票案例的思考
出现了两个问题
一个是同一张票出现三次:这是因为有sleep方法,线程暂停时,其他线程也就绪了,也就导致第一个线程执行下去,还没执行到tikect–,其他线程也同时执行了
另一个是出现了负数票:这是因为到最后的时候,第一个线程执行下去执行完之后,将ticket–执行了,所以其他线程执行时,刚开始ticket>0可以执行,就绪后,ticket改变,所以输出的时候会出现负值
同步代码块
具体代码
要想破坏掉三个条件同时成立,只能破坏第三个条件,也就是不让多条语句操作共享数据,也就是让线程一个一个进行,而不是多个线程同时去抢执行权并操作
这里用synchronized(任意对象){
(多条操作共享数据的语句)
}
注意这里的任意对象要在类中单独定义一个,保证是一个具体的对象,而不能是将“new Object()”当作参数
好处和弊端
同步方法
就是将同步代码块放到一个方法中,这个方法被synchronized修饰,使用时,调用该方法
同步一般方法
注意,想要实现加锁,其整个类中synchornized的参数必须是同一个锁,也就是同一个对象做参数,因此可以测试出来该方法的参数是哪个对象
一般同步方法参数是this,this表示当前类对象,可以理解成指向对象本身的一个指针。通俗地说就是表示当前类对象”自己“,它是在对象被创建时自动产生的。我们使用this,可以用来调用本类的属性、方法、构造方法
同步静态方法
首先要将静态方法里涉及到的成员变量改为静态变量
而且,该方法要加上static修饰符
经过测试,该synchornized的参数是类名.class
总结
线程安全的类
这三个类只在线程安全的环境下使用,其他环境用对应的代替方法
注意,其中Vetor方法在线程安全环境下也不被使用,而是用Collections的一个方法来替代
Lock锁
简介
注意,这里定义Lock对象的时候,采用多态的方法,new的是Lock的实例化子类,因为Lock是一个接口
完整代码演示(效果和synchornized一样)
在代码块前面加上lock.lock()//加锁
最后在代码块后面 lock.unlock()//释放锁
注意,一般加上try-finally,防止出现异常终止程序