文档章节

lock和wait+signal

精通吹水
 精通吹水
发布于 2016/04/15 17:02
字数 830
阅读 239
收藏 15
点赞 1
评论 0

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等。

© 著作权归作者所有

共有 人打赏支持
精通吹水
粉丝 18
博文 56
码字总数 55035
作品 0
人事招聘
C++11 多线程 Mutex篇 (续)

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

SHIHUAMarryMe
2016/03/19
108
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
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
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
命令行模式处理 cifs 进程锁死

在console命令下执行 1.查询被锁状态 : lock status -h : lock status -f -p cifs : lock status -o admin -p cifs : lock status -f "/vol/Share1/Folder/File.doc" -p 2.解锁用户 : lock b......

Kzhou
2014/04/20
0
0
erlang global:trans/4函数

根据erlang文档 trans(Id, Fun, Nodes, Retries) -> Res | aborted >Sets a lock on Id (using set_lock/3). If this succeeds, Fun() is evaluated and the result Res is returned. Return......

格通
2016/11/02
7
0
java 线程同步 字符串 锁

有个 java 同步的问题,我是用 一个字符串 作为 synchronized 锁住的对象。代码 如下 import java.util.ArrayList; import java.util.Date; class Locktest{ private int i = 10; } class L......

xianwu13
2012/12/17
1K
3
C++11: Mutex和Lock

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

SHIHUAMarryMe
2016/03/18
246
0
Intrinsic Locks and Synchronization

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrin......

恋空御月
2016/08/19
5
0
C++11中std::lock_guard的使用

互斥类的最重要成员函数是lock()和unlock()。在进入临界区时,执行lock()加锁操作,如果这时已经被其它线程锁住,则当前线程在此排队等待。退出临界区时,执行unlock()解锁操作。更好的办法是...

fengbingchun
2017/11/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

python3.6用的外库遇到的问题

要用到wmi库 pip install wmi 装后不能用还要安装pywin32库。 要用到crypto加密模块安装pip instal pycrypto装后不能用。要安装pycryptodome。...

oisan_
13分钟前
0
0
select, poll, epoll I/O复用介绍

什么是I/O复用? 内核监视多个文件描述符(I/O文件句柄),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知应用程序进行相应的读写操作。 I/O多路复用又被称为“事件驱动”(比如读写事...

xiaoxlm
13分钟前
0
0
【Spring 系列 给IOC容器添加组件的几种方式总结】

给Spring 注册Bean的几种方式总结。其中使用@Import注解是Spring Boot 完成自动配置的一个核心注解。 1、Spring 中给IOC容器添加组件的几种方式 在Spring的配置文件中,配置Bean(基于XML方式...

HansonReal
14分钟前
4
0
bootstrapTable语言包设置

###方法一引入不同的语言包 <script src="bootstrap-table-zh-CN.js"></script> ###方法二引入全语言包 <script src="bootstrap-table-locale-all.min.js"></script>//然后在初始化前设计默......

momo1987
15分钟前
0
0
Saltstack 常用命令

1、拷贝文件到客户端 # salt 'slaver.test.com' cp.get_file salt://apache.sls /tmp/cp.txt 2、拷贝目录到客户端 # salt 'slaver.test.com' cp.get_dir salt://test /tmp 3、显示存活的客户......

硅谷课堂
16分钟前
0
0
致初学者-如何学好Python这门编程语言?[图]

致初学者-如何学好Python这门编程语言?[图]: 对于很多Python3初学者,往往会面临以下问题:Python2和Python3我该学习哪一个?是否要安装Linux系统学习Python?Python3有各种版本我该安装哪...

原创小博客
19分钟前
1
0
E31---setopt=protected_multilib=false

今天在云服务器上装nginx,需要先安装一些依赖库比如zlib, ,但是安装zlib时候报错。 yum install -y zlib zlib-devel 1 (-y 指的是如果需要选yes no的自动y)下面是报错 Protected multil...

侠客行之石头
23分钟前
0
0
HTTP常见面试题

Http与Https的区别: HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头 HTTP 是不安全的,而 HTTPS 是安全的 HTTP 标准端口是80 ,而 HTTPS 的标准端口是443 在OSI 网络模型中,H...

JK_OPERA
24分钟前
0
0
python爬取站长素材网页图片保存到ppt中

网站地址:http://sc.chinaz.com/tupian/index.html 直接上代码: import requestsfrom bs4 import BeautifulSoupfrom pptx import Presentationfrom pptx.util import Inchesimpor......

你为什么不吃药
26分钟前
1
0
Ubuntu 18.04 swap空间的修改

一、准备工作 执行“sudo swapon -s”命令,查看是否已经存在swap file 二、修改swap file # 如果第一步存在swapfile则需要先禁用sudo swapoff /swapfile# 修改swap 空间的大小为2Gs...

Iceberg_XTY
29分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部