首先我们来了解一下syncronized块和锁运行的基本原理,我们知道syncronized块的运行是依赖于锁而进行的。

假如把一个对象比喻成一个内部有很多小房子的大房子,有一些小房子没有门,人们随便可以进出。但还有一些小房子是带锁的,这些锁都一模一样,大厅中只放了一把钥匙,有一个人要进入一个带锁的房子,他就会把钥匙带走,这样下一个人就无法进入任何一个带锁的房子了,只有当这一个人出来,这时候他就会把钥匙带出来,这样下一个人就可以进入了。

Syncronized后面括号里跟的对象便是我们的大房子,不在同步块中的内容便是没锁的小房子,在同步块中的内容便是我们带锁的小房子。假如一个线程进入了对象任何一个同步块,那这个线程就拿到了钥匙,其他要访问这个类中任何同步块的线程就必须要等待。

下面就举个例子,这是我们的多线程程序:

Ps(非常重要):很多同学可能发现syncronized没用,加了之后也还是各跑各的,那是因为你创建了好几个不同的对象,然后每个都启动,syncronized是对于同一对象,但不同线程而言的,就像下面程序中这样。

public class Test{

public static voidmain(String []args)

{

Kk k=new Kk();

Thread t=new Thread(k);

Thread t2=new Thread(k);

t.start();

t2.start();

}

}

class Kk  extends Thread{

public void run(){

int i=0;

for(i=1;i<50;i++)

{

System.out.print(i+” ”);

}

}

}

注:下面的修改代码都是在这个的基础上进行修改。

在没有同步的情况下,打印的结果是这样的:

1 2 3 1 4 2 5 6 7 8 9 10 11 12 3 13 14 4 1516 17 18 19 5 20 21 6 22 23 24 25 26 27 7 28 29 30 31 32 33 34 8 35 36 37 38 910 39 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 3435 36 37 38 39 40 41 40 42 43 44 41 42 43 44 45 45 46 47 48 49 46 47 48 49

杂乱无章,毫无规律可寻。

假如我们用syncronized对一部分进行一下限制,也就是给房子加一个锁:

synchronized(this) {

for(i=1;i<50;i++)

{

System.out.print(i+" ");

}

}

这时的输出结果是这样:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 2627 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 1 2 3 4 56 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 3334 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

显然已经是有序的了,k线程处理完之后,才是k1线程进行处理。

然后我们再验证几个结论:

(1)房子里只有一把钥匙。

此时将代码作如下更改:

public void run(){

synchronized(this){

for(int i=1;i<50;i++)

{

System.out.print(i+" ");

}

}

synchronized(this){

for(int i=100;i<150;i++)

{

System.out.print(i+" ");

}

}

}发现得到的结果为:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1718 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 4344 45 46 47 48 49 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 1 2 3 4 5 6 7 8 910 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3536 37 38 39 40 41 42 43 44 45 46 47 48 49 100 101 102 103 104 105 106 107 108109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148149

此时基本可以断定,当一个线程进入任意一个同步块的时候,所有的同步块都不允许其他线程访问了,也就是房子只有一把钥匙。(当然不严谨)

(2)只有在同一座大房子里才能完成synchronized(obj)

修改主函数代码为:

Kk k=new Kk();

Kkk2=new Kk();

Threadt=new Thread(k);

Threadt2=new Thread(k2);

t.start();

t2.start();

线程中代码修改为:

synchronized(this) {

for(i=1;i<50;i++)

{

System.out.print(i+" ");

}

}

然后输出为:

1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 317 18 4 5 19 20 6 21 7 8 22 9 10 23 24 11 12 25 13 26 27 14 15 28 16 17 29 1819 20 30 21 22 31 32 23 24 25 33 34 26 27 35 36 28 29 37 38 30 31 39 40 32 3341 42 34 35 43 44 36 37 45 46 38 39 47 48 40 41 42 49 43 44 45 46 47 48 49

这说明对于两个对象而言,是没用的。

(2钥匙被带走之后,其他人还可以访问其他未上锁的房子。这个我们只需要找一个特例就好:

修改代码为:

synchronized(this) {

for(int i=1;i<50;i++)

{

System.out.print(i+" ");

}

}

for(inti=1;i<50;i++)

{

System.out.print(i+" ");

}

此时输出为:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2829 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 1 1 2 2 3 3 4 45 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 1920 20 21 21 22 22 23 23 24 24 25 25 26 27 28 29 30 31 32 33 34 35 36 37 38 3940 41 42 43 44 45 46 47 48 49 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1920 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 4546 47 48 49 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 4748 49

这时我们发现,前五十个是有序的,而后一百个是在交替输出,也就是说t2线程拿着钥匙的时候,t还在访问没有锁的部分。

好的,然后接下来,我们讨论一下wait,notify的问题。

说到wait就免不了要说sleep,我们知道sleep函数的运行原理很简单,就是你在线程中调用Thread.sleep函数,然后确定睡眠时间,然后当前线程就会阻塞那么长的时间。

举个例子:

修改代码为:

synchronized(this) {

for(int i=1;i<50;i++)

{

System.out.print(i+" ");

}

try {

Thread.sleep(10000);

}catch(InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

此时输出为:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 3031 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 1 2 3 4 5 6 7 8 9 1011 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 3637 38 39 40 41 42 43 44 45 46 47 48 49

此时输出结果是一样的,但很明显的是,中间等待了很长一段时间,也就是说,当一个线程在sleep等待的时候,他依然持有钥匙,别的线程依然进不来。

而wait与sleep的区别就在这儿,线程在wait的同时,会把钥匙交出来,也就是让别的线程进来执行(当然也是指允许一个)。

我们举个例子:

修改代码为:

synchronized(this) {

for(int i=1;i<50;i++)

{

System.out.print(i+" ");

}

try {

this.wait();

}catch(InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

此时输出为:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 3031 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 1 2 3 4 5 6 7 8 9 1011 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 3637 38 39 40 41 42 43 44 45 46 47 48 49

我们发现,此时第一个线程还在同步块中阻塞着,但是第二个线程已经进入代码开始执行,说明当第一个线程进入wait状态之后,已经将钥匙送了出去,这时候显然,所有的同步块都可以被其他线程访问到,又成了一个资源抢夺的问题。

然后就是Notify的作用,这个函数无非也就是将其他在等待的线程唤醒,Notify唤醒单个(随机唤醒一个),NotifyAll唤醒所有(唤醒顺序也是不确定的),对于简单的无参数的wait,其实也就是这么点东西。

我们用wait,notify实现一个简单的功能,就是两个线程交替打印1 1 2 2…….

我们可以修改代码为:

synchronized(this) {

for(int i=1;i<50;i++)

{

System.out.print(i+" ");

try {

this.notify();

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

然后输出结果为:

11 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 1717 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 3030 31 31 32 32 33 33 34 34 35 35 36 36 37 37 38 38 39 39 40 40 41 41 42 42 4343 44 44 45 45 46 46 47 47 48 48 49 49

当然wait,notify也是对于同一个对象而言的,调用一个对象的wait的同时,可以让当前线程等待,同时释放调用的这个对象的锁。然后调用这个对象的Notify,释放那些曾经调用这个对象的wait函数的线程。

浅谈一下线程中synchronized块、wait,notify的用法相关推荐

  1. python线程死锁的原因,浅谈Python线程的同步互斥与死锁

    线程间通信方法 1. 通信方法 线程间使用全局变量进行通信 2. 共享资源争夺 共享资源:多个进程或者线程都可以操作的资源称为共享资源.对共享资源的操作代码段称为临界区. 影响 : 对共享资源的无序操 ...

  2. python同步锁和互斥锁的区别_浅谈Python线程的同步互斥与死锁

    这篇文章主要介绍了浅谈Python线程的同步互斥与死锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 线程间通信方法 1. 通信 ...

  3. 浅谈ThreadPool 线程池(引用)

    出自:http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html 浅谈ThreadPool 线程池 相关概念: 线程池可以看做容纳线程的 ...

  4. 浅谈V8引擎中的垃圾回收机制

    浅谈V8引擎中的垃圾回收机制 这篇文章的所有内容均来自 朴灵的<深入浅出Node.js>及A tour of V8:Garbage Collection,后者还有中文翻译版V8 之旅: 垃 ...

  5. python中if和elif的区别_浅谈对python中if、elif、else的误解

    今天下午在练习python时用了"if...if...else..."的分支结构,结果运行出来吓我一跳.原来我想当然的认为"if...if...else..." ...

  6. 浅谈linux线程模型和线程切换

    本文从linux中的进程.线程实现原理开始,扩展到linux线程模型,最后简单解释线程切换的成本. 刚开始学习,不一定对,好心人们快来指正我啊啊啊!!! linux中的进程与线程 首先明确进程与进程的 ...

  7. python执行不了elif_浅谈对python中if、elif、else的误解

    今天下午在练习python时用了"if...if...else..."的分支结构,结果运行出来吓我一跳.原来我想当然的认为"if...if...else..." ...

  8. python中分支语句elif与else的区别_浅谈对python中if、elif、else的误解

    今天下午在练习python时用了"if...if...else..."的分支结构,结果运行出来吓我一跳.原来我想当然的认为"if...if...else..." ...

  9. html 怪异模式,CSS_浅谈CSS编程中的怪异模式,怪异模式盒模型 今天学习了 - phpStudy...

    浅谈CSS编程中的怪异模式 怪异模式盒模型 今天学习了一下css3的box-sizing属性,顺便又温习了一下css的盒模型,最后觉得有必要对盒模型做一个全面整理. 先不考虑css3的情况,盒模型一共 ...

最新文章

  1. 10a大电流稳压芯片_稳压二极管你见过,但是它的这些参数你知道吗
  2. java在线书城系统_二手书城系统 本设计为基于JAVA的网上书店系统 - 下载 - 搜珍网...
  3. Oracle分页(limit方式的运用)
  4. VUE.JS 使用axios数据请求时数据绑定时 报错 TypeError: Cannot set property 'xxxx' of undefined 的解决办法...
  5. VC++中Depends工具的使用和DLL函数的动态调用方式示例
  6. Swift中switch比较元组类型
  7. java中ajax删除,ajax删除 post方法
  8. Camera360与全球1.8亿用户共同创造更美的照片
  9. 如何制作印章_如何用Photoshop制作个性印章/文字图片
  10. 第十三期:你所了解的javascript?
  11. 函数:MySQL中字符串匹配函数LOCATE和POSITION使用方法
  12. postgresql 远程用户_构建Python pandas基于SSH远程MySQL和PostgreSQL的数据分析
  13. pom.xml中添加阿里云Maven中央仓库配置
  14. HDU1012 Calculate e
  15. 欧姆龙nb触摸屏通信_欧姆龙触摸屏 NB系列
  16. C#:VARCHART XGantt 5.2.0.167-2022-08-18-UPDATE
  17. STM32CubeIDE 使用技巧和说明
  18. (后台)Openbravo如何实现业务事件监听处理
  19. freeradius在AP控制器设备中test-aaa 显示timeout的解决方案
  20. CF1320E Treeland and Viruses

热门文章

  1. 将idea设置为中文
  2. 学习ofbiz 订单支付设计
  3. 运行日志Log文件c++实现
  4. jquery3.2 在线引用地址
  5. 超鸿蒙是什么意思,帝垣的组词_拼音_意思_近反义词(造句)
  6. if条件语句基本语法
  7. 解析电子墨水屏技术(工作原理与LCD的区别)【转】
  8. android自定义排班,Android实现一周时间早中晚排班表
  9. js在指定的td中插入html元素,js在指定位置增加节点函数insertBefore()用法实例
  10. 硕士研究生期间,必须了解的一些科研工具