文档章节

lock和wait+signal

精通吹水
 精通吹水
发布于 2016/04/15 17:02
字数 830
阅读 283
收藏 15

lock和wait+signal

在编程中,我们经常使用多线程来提升性能,所以这就涉及到互斥和同步的问题了。而在编程中,我们一般都是通过如下方式来完成多线程的互斥和同步:

  • lock | unlock
  • signal + wait(timeout)
  • join
  • sleep

C语言

在Linux C编程中,我们通常使用pthread类库来完成跨平台的多线程控制,如下是几个常用的API:

  • pthread_mutex_lock():占有互斥锁(阻塞操作)
  • pthread_mutex_unlock(): 释放互斥锁
  • pthread_cond_signal(): 唤醒第一个调用pthread_cond_wait()而进入睡眠的线程
  • pthread_cond_wait(): 等待条件变量的特殊条件发生
  • pthread_cond_timedwait():等待条件变量的特殊条件发生或者timeout
  • pthread_join():阻塞当前的线程,直到另外一个线程运行结束
  • sleep() : 休眠固定时间,不过这个API是Linux原生提供,不能跨平台。

注意:**pthread类库是glibc(绝大多数Linux平台标准C库。)的一部分。这些功能都是通过中断号进入内核来完成的,而非仅仅做了Linux兼容API。**具体可见 glibc-2.23\sysdeps\nacl\nacl-interface-list.h ,声明wait(timeout)功能中断号文件。

Java

在Java中,多线程的控制已经是一个统一标准了,一般都是通过Java原生API或者JUC来实现并发控制。这里来说说原生的API:

  • synchronized : 实现了lock 和 unlock的功能
  • Object#wait : 等待信号发生,并且可以实现超时等待
  • Object#notify : 通知信号发生
  • Object#notifyAll :通知信号发生
  • Thread#join :阻塞当前的线程,直到另外一个线程运行结束
  • Thread#sleep : 休眠固定时间

通过这些API,我们基本上能实现Java的多线程并发控制,当然了可以使用最新的JUC并发库的API。而这些API底层也是可以通过pthread这个C库来实现。

示例-Timer

Java中Timer的实现原理就是通过 wait 和 notify 以及 synchronized 来实现的:

Timer timer = new Timer();
timer.schedule(new TimerTask() {
	@Override
	public void run() {

	}
}, 1000);

其实,Timer持有TimerImpl,其实Impl就是一个Thread实现,它一直阻塞等待task的到来,见run代码:

public void run() {
	while (true) {
		TimerTask task;
		synchronized (this) {
			// need to check cancelled inside the synchronized block
			if (cancelled) {
				return;
			}
			//等待任务
			if (tasks.isEmpty()) {
				if (finished) {
					return;
				}
				// no tasks scheduled -- sleep until any task appear
				try {
					//等待任务加入后,会通过notify来通知它可以运行
					this.wait();
				} catch (InterruptedException ignored) {
				}
				continue;
			}
			....
			if (timeToSleep > 0) {
				// sleep!
				try {
					//延迟执行代码
					this.wait(timeToSleep);
				} catch (InterruptedException ignored) {
				}
				continue;
			}

			// no sleep is necessary before launching the task
			...
		}

		...
		try {
			//具体执行任务
			task.run();
			taskCompletedNormally = true;
		} finally {
			...
		}
	}
}

可以看到TimerImpl的run代码会通过wait来阻塞等待任务加入queue,然后通过notify告知它可以运行task。timer#schedule最后会调用TimerImpl#insertTask,具体代码如下:

private void insertTask(TimerTask newTask) {
	// callers are synchronized
	tasks.insert(newTask);
	this.notify();
}

**所以任务加入队列后,通过notify来告知阻塞在等待任务的线程(TimerImpl#run)。**这样子就实现了Timer的功能了,并且通过wait(timeout)实现了delay的功能。

总结

多线程的控制,其实大多都是依赖:

  • lock
  • signal + wait

这两种类型的API来完成并发控制。

而在此基础上,我们可以实现各种各样的多线程并发控制,比如说:MQ,CountDownLatch等。

© 著作权归作者所有

共有 人打赏支持
上一篇: debugger
下一篇: TCP 的那些事儿
精通吹水
粉丝 18
博文 56
码字总数 55035
作品 0
人事招聘
私信 提问
C++11 多线程 Mutex篇 (续)

Mutex篇续 上一篇传送门 std::uniquelock::trylock_until 尝试调用uniquelock所管理的对象(注:该对象也必须支持trylockuntil)的trylockuntil(abstime)给所管理的互斥量上锁. (注:trylockun...

SHIHUAMarryMe
2016/03/19
108
0
InnoDB Lock Modes

InnoDB Lock Modes http://dev.mysql.com/doc/refman/5.7/en/innodb-lock-modes.html InnoDB implements standard row-level locking where there are two types of locks, shared (S) locks......

秋风醉了
2015/11/13
0
0
Locks in Java(翻译blog)

simple-lock from Java 5 the package java.util.concurrent.locks contains several lock implementations, so you may not have to implement your own locks. But you will still need to......

o0无忧亦无怖
2015/10/08
39
0
MySQL表锁_LOCK TABLES_UNLOCK TABLES

MySQL表锁LOCK TABLESUNLOCK TABLES mysql5.6 参考文档:http://dev.mysql.com/doc/refman/5.6/en/lock-tables.html 锁表和解锁表的基本语法 LOCK TABLES tblname [[AS] alias] locktype [,......

秋风醉了
2014/11/06
0
0
C++11: Mutex和Lock

Mutex全名mutual exclusion(互斥体),是一个可加锁对象(lockable object),用来协助采取独占排他方式控制对资源的并发访问.这里的资源可能是个object,也可能是多个object的组合。为了获得独占式...

SHIHUAMarryMe
2016/03/18
246
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周三乱弹 —— 风扇写着先生请自爱

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @蚂蚁哈哈哈 :分享陈奕迅的单曲《落花流水》 《落花流水》- 陈奕迅 手机党少年们想听歌,请使劲儿戳(这里) @车谷 :我发现每天上班都好困 ...

小小编辑
18分钟前
2
0
centos7重置密码、单用户模式、救援模式、ls命令、chmod命令

在工作当中如果我们错误的配置了文件使服务器不能正常启动或者忘记密码不能登录系统,如何解决这些问题呢?重装系统是可以实现的,但是往往不能轻易重装系统的,下面用忘记密码作为例子讲解如...

李超小牛子
今天
3
0
Python如何开发桌面应用程序?Python基础教程,第十三讲,图形界面

当使用桌面应用程序的时候,有没有那么一瞬间,想学习一下桌面应用程序开发?行业内专业的桌面应用程序开发一般是C++,C#来做,Java开发的也有,但是比较少。本节课会介绍Python的GUI(图形用...

程序员补给栈
今天
6
0
kafka在的使用

一、基本概念 介绍 Kafka是一个分布式的、可分区的、可复制的消息系统。它提供了普通消息系统的功能,但具有自己独特的设计。 这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统...

狼王黄师傅
今天
3
0
Android JNI总结

0x01 JNI介绍 JNI是Java Native Interface的缩写,JNI不是Android专有的东西,它是从Java继承而来,但是在Android中,JNI的作用和重要性大大增强。 JNI在Android中起着连接Java和C/C++层的作...

天王盖地虎626
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部