同步函数
函数和同步代码块都是封装,两者结合就是同步函数
把synchronized关键字作为修饰符放在函数上就实现了同步函数,无需对象锁
将需要同步的代码单独封装为一个函数,并加上synchronized关键字就实现了同步函数
函数需要被对象调用,那么函数都有一个所属对象的引用就是this,所以同步函数使用的锁是this
[java] view plaincopy
1. class Ticket implements Runnable
2. {
3. private int tick=100;
4. Object obj = new Object();
5. public void run()
6. {
7. while(true)
8. {
9. show();
10. }
11. }
12. //直接在函数上用synchronized修饰即可实现同步
13. public synchronized void show()
14. {
15. if(tick>0)
16. {
17. try
18. {
19. //使用线程中的sleep方法,模拟线程出现的安全问题
20. //因为sleep方法有异常声明,所以这里要对其进行处理
21. Thread.sleep(10);
22. }
23. catch (Exception e)
24. {
25. }
26. //显示线程名及余票数
27. System.out.println(Thread.currentThread().getName()+"..tick="+tick--);
28. }
29. }
30. }
静态同步函数的锁
同步函数被静态static修饰后,使用的锁不是this,因为静态方法中不可以定义this。静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象:类名.class,该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象,也就是类名.class
参阅单例设计模式-懒汉式
[java] view plaincopy
1. class Single
2. {
3. private static Single s = null;
4. private Single(){}
5. public static Single getInstance()
6. {
7. if(s==null)
8. {
9. synchronized(Single.class)
10. {
11. if(s==null)
12. s = new Single();
13. }
14. }
15. return s;
16. }
17. }//同步代码块加入判断的原因:如果第一个线程进入到第一个if代码块,此时并还没获取锁,此时虚拟机切换给第二个线程,它也进来了if代码块,并且此时获取锁,new一个对象,然后返回。接着虚拟机切换给第一个线程,它这时候才获取锁,此时如果没有第二个if判断,就会再new 一个对象,这就不能保证类的对象唯一性。
|
|