售票的例子。
--------------------------------------
多线程的安全问题:
售票时居然会发生打印负号票的情况。
造成安全问题的原因:
多条语句在对同一数据资源进行操作,而这些语句被多个线程分开执行时,容易出现数据资源错误。
而到值安全问题的产生。
解决思想:
那就是将这多条语句进行封装,一次只能让一个线程都执行完后,才让另一个线程执行该代码。
解决方式:
同步 。
同步的原理:就是将代码进行封装,并加锁。
同步的前提:
1,要有两个或者两个异常的线程。
2,必须多个线程使用的是同一个锁。
同步的格式:
1,同步代码块。
synchronized(obj)
{
需要被同步的语句。
}
2,同步函数。
其实就是在函数上加上一个synchronized修饰符。
两个格式有什么区别?
同步代码块可以让任意对象作为锁存在。只要保证多个线程用的是同一个对象(锁)即可。
同步函数使用的锁是this。
注意:当同步函数被static修饰时,那么这时使用的锁就不是this了。因为静态函数不具备this引用。
使用的锁是 该类对应的字节码文件对象。该对象的表现形式是: 类名.class
不得不提:单例设计模式的懒汉式。
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
当多线程并发访问getInstance()方法时,容易出现线程安全问题。不能保证对象的唯一性。
这时我们需要将其同步。那么将该函数用synchronized 关键字修饰是可以解决安全问题的。
但是效率很低。
这时可以采取一种优化的方式。双重判断的形式。
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
s = new Single();
}
}
return s;
}
|
|