
CRITICAL_SECTION Mutex核心对象
InitializeCriticalSection() CreateMutex()
OpenMutex()
EnterCriticalSection() WaitForSingleObject();
WaitForMultipleObjects();
MsgWaitForMultipleObjects();
LeaveCriticalSection() ReleaseMutex();
DeleteCriticalSection() CloseHandle();
为了能够跨进程使用同一个mutex,在产生mutex时指定其名称,不使用句柄。
----产生一个互斥器Mutex
Mutex是一个核心对象critical section 释放,被保存在系统核心之中,并且和其他核心对象一样,有所谓的引用计数器。利用CreateMutex()产生一个mutex:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD 安全属性
BOOL bInitialOwner, // initial owner mutex的拥有者,如果设置为TRUE,则拥有者为调用者
LPCTSTR lpName // object name mutex的名称,是一个字符串,可以根据名称使用
mutex

);
如果不需要一个mutex,可以调用CloseHandle()将它关闭。
----打开一个互斥器(Mutex)
如果mutex已经产生,并且有一个名字。那么任何其他的线程和进程都可根据名称来打开那个mutex.
HANDLE OpenMutex(
DWORD dwDesiredAccess, // access
BOOL bInheritHandle, // inheritance option
LPCTSTR lpName // object name
);
----锁住一个互斥器(Mutex)
l 每次你使用entercriticalsection时,请不要忘了在函数的所有可能返回的地方都加上leavecriticalsection。海关同时拥有许多权利,归纳成十四种,即:检查权、查阅权、复制权、查问权、查验权、查询权、稽查权、扣留权、连续追缉权、权、佩戴和使用武器权、强制执行权、施加封志权和税费征收权。第Ⅰ部分必备知识第1章 错误处理1 1 定义自己的错误代码1 2 errorshow示例程序第2章 字符和字符串处理2 1 字符编码2 2 ansi字符和unicode字符与字符串数据类型2 3 windows中的unicode函数和ansi函数2 4 c运行库中的unicode函数和ansi函数2 5 c运行库中的安全字符串函数2 5 1 初识新的安全字符串函数2 5 2 在处理字符串时如何获得更多控制2 5 3 windows字符串函数2 6 为何要用unicode2 7 推荐的字符和字符串处理方式2 8 unicode与ansi字符串转换2 8 1 导出ansi和unicode dll函数2 8 2 判断文本是ansi还是unicode第3章 内核对象3 1 何为内核对象3 1 1 使用计数3 1 2 内核对象的安全性3 2 进程内核对象句柄表3 2 1 创建一个内核对象3 2 2 关闭内核对象3 3 跨进程边界共享内核对象3 3 1 使用对象句柄继承3 3 2 改变句柄的标志3 3 3 为对象命名3 3 4 终端服务命名空间3 3 5 专有命名空间3 3 5 复制对象句柄第Ⅱ部分 工作机制第4章 进程4 1 编写第一个windows应用程序4 1 1 进程实例句柄4 1 2 进程前一个实例的句柄4 1 3 进程的命令行4 1 4 进程的环境变量4 1 5 进程的关联性4 1 6 进程的错误模式4 1 7 进程当前所在的驱动器和目录4 1 8 进程的当前目录4 1 9 系统版本4 2 createprocess函数4 2 1 pszapplicationname和pszcommandline参数4 2 2 psaprocess。
一旦没有任何线程拥有mutex,这个mutex便处于激发状态。因此,如果没有任何线程有用mutex,Wait()便会成功。
BOOL ReleaseMutex(
HANDLE hMutex // handle to mutex
);
Mutex的拥有权并不是属于产生它的线程,而是那个最后对Mutex进行Wait..()操作并且没有进行ReleaseMutex()操作的线

程。线程拥有mutex就像线程进入critical section一样,一次只能有一个线程拥有该mutex.
----处理被舍弃的互斥器(Mutexes)
在一个程序中,线程绝对不应该在它即将结束前还拥有一个mutex,因为这意味着线程没有能够适当的清初其资源。
因为某种原因,线程可能没有在结束前调用ReleaseMutex().为了解决这个问题,mutex有一个非常重要的特性。这个性质是同步机制中独一无二的。
任何时候想锁住超过一个以上的同步对象,就有死锁的潜在病因。如果在相同的实际把所有的对象都锁住,问题就可以解决。
新版SwapList();
typedef struct _Node
{
struct _Node *next;
int data;
}Node;
typedef struct _List
{
Node *head;
HANDLE hMutex;
}List;
void SwapLists(struct List *list1,Struct List *list2)
{
struct List *tmp_list;
HANDLE arrhandles[2];
arrhandles[0]=list1->hMutex;
arrhandles[1]=list2->hMutex;
WaitForMultipleObjects(2,arrHandles,TRUE,INFINITES);
/*相关操作*/
ReleaseMutex(arrhandles[0]);
ReleaseMutex(arrhandles[1]);
}
-----信号量(Semaphores)
信号量机制可以有效的解决生产者和消费者问题。
当要访问数据的时候,先查看n值,(n的值代表还有多少个线程能访问资源)如果n值大于0,该线程能访问资源,线程进入后把n值减一。互斥锁:只要被锁住,其他任何线程都不可以访问被保护的资源。互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源。
,并非单独一个线程就不能够拥有所有的锁定。
mutex是sempahore的一种退化。如果你产生一个semaphore并令最大值为1,那就是一个mutex.故mutex又称为binary semaphore.
在Win32中semaphores被使用的情况少,因为有Mutex存在。
a.产生信号量CreateSemaphore();
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // SD

LONG lInitialCount, // initial count semaphore的初值,》0&&《IMaximumCount
LONG lMaximumCount, // maximum count 线程的最多个数
LPCTSTR lpName // object name 信号量的名字
);
如果该互斥锁已被另一个线程锁定和拥有,则调用线程将阻塞,直到该互斥锁变为可用为止。非分离的线程终止时,其线程id和退出状态将保留,直到另外一个线程调用pthread_join.分离的线程在当它终止时,所有的资源将释放,我们不能等待它终止。非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
b.解除锁定(Releasing Locks)
调用ReleaseSemaphore(),并将现值加1,并传回semaphore的前一个现值。
BOOL ReleaseSemaphore(
HANDLE hSemaphore, // handle to semaphore
LONG lReleaseCount, // count increment amount
LPLONG lpPreviousCount // previous count
);
与mutex不同的是,调用ReleaseSemaphore()的那个线程,并不一定就是调用Wait..()的那个线程。任何线程都可以在任何时间调用ReleaseSemaphore(),解除被任何线程锁定的semaphore.
-----事件(Event Objects)
当一个手动复原的事件对象的状态被置为有信号状态时,该对象状态将一直保持有信号状态,直至明确调用resetevent函数将其置为无符号状态。在前面一文中已经知道this,其指向不是指向函数自身,也不是指向函数的作用域,一旦创建一函数,系统会默认的生成一个名为this的关键字,它的指向与它所运行的坏境,也就是上下文有关,this是在运行时进行绑定的,它的上下文取决于函数调用的各种条件(函数调用(全局的),方法调用,构造函数调用,间接调用),this的绑定与函数声明的位置没有任何关系,只取决于函数的调用方式,也就是说,它链接到运行该函数的对象,我们之所以频繁的用this,其根本目的就是在找准对象,并对其进行dom相关操作,往往是为了找某个指定的元素,但是又由于this的使用比较特殊,除非特意,大多数时候,我们是不希望找出window对象的,所以非期望对象值总会令你困扰, 使用this时,什么时候出现问题。应用程序启动:cmydocument对象被创建-》cmyview对象被创建-》其它视图对象被创建-》视图窗口被创建-》cmyview::oncreate函数被调用(如果被映射)-》cmydocument::onnewdocument函数被调用-》cmyview::oninitialupdate函数被调用-》调用cmyview::onupdate-》初始化视图。
a.产生一个event对象

HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
自动重置事件被设置为激发状态后,会唤醒“一个”等待中的线程,然后自动恢复为未激发状态。cevent的构造函数默认创建一个自动重置的事件,而且处于未激发状态。事件对象可以一两种方式创建,一种为自动重置,在其他线程使用 waitforsingleobject等待到事件对象变为有信号后该事件对象自动又变为无信号状态,一种为人工重置在其他线程使用 waitforsingleobject等待到事件对象变为有信号后该事件对象状态不变。
ncheck的值为0表示按钮未被选择,为1表示按钮被选择,为2表示按钮处于不确定状态(仅用于复选框)。设备号的颜色:设备号显示为灰色(zf201)时表示设备处于就地状态,当设备号显示时(zf201),表示设备处于集控状态,当设备号闪烁时表示设备处于故障状态,表示热继电器动作、变频器故障或软启动器故障。 在十天干中,所有阳干都表示处于不断上升和不断扩张的增强状态, 所有阴干都表示处于不断下降和不断收缩的减弱状态。
LPCTSTR lpName // object name
);
SetEvent() 把event对象设为激发状态
ResetEvent() 把event对象设为非激发状态
手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态。nscondition可以调用wati方法控制某个线程处于等待状态,直到其他线程调用signal(此方法唤醒一个线程,如果有多个线程在等待则任意唤醒一个)或者broadcast(此方法会唤醒所有等待线程)方法唤醒该线程才能继续。2、signal:唤醒在此lock对象上等待的单个线程,如果所有的线程都在该lock对象上等待,则会选择随机唤醒其中一个线程。
同步机制总结
a.Critical Section
在操作系统中,进程是占有资源的最小单位(线程可以访问其所在进程内的所有资源,但线程本身并不占有资源或仅仅占有一点必须资源)。如果不在同一进程内(包括远程进程),代理对象将向rpc管理的一个线程池请求一个线程(rpc线程)来专门向另一进程中的sta线程的隐藏窗口发送消息,而不是代理对象直接发送消息,以防止外界线程由于网络等不稳定因素而导致挂起。②、循环死锁:线程a占有资源a,线程b占有资源b,线程c占有资源c,线程a申请占有资源b,同时要求占有资源b之后才释放资源a,而线程b申请占有资源c,同时要求占有资源c之后才释放资源b,线程c申请占有资源a,同时要求占有资源a之后才释放资源c,这样线程互相永久等待对方释放资源,这就是循环死锁。
b.Mutex
它是一个核心对象,可以在不同的线程之间实现“排他性占有”,甚至那些线程属于不同的进程。它是一个核心对象。
如果拥有mutex的那个线程结束,则会产生一个“abandoned”错误信息。可以使用Wait...()等待一个mutex.可以具名,因此被其他进程开启。只能被拥有它的那个线程释放。
c.Semaphore
semaphore被用来追踪有限的资源。它是 一个核心对象,没有拥有者。可以具名,因此可以被其他进程开启。
可以被任何一个线程释放(released).
d.Event Object
在glusterfs 3.3版本中增加的新功能包括: 统一的文件和对象存储:glusterfs实现了openstack里的对象存储api提供同步读取和写入文件或对象的数据的访问。结束语:顺便提一下为什么会有inetd服务器的原因critical section 释放,因为如果没有的话,假设在系统中有10个请求服务端,然后就会创建10个接受进程来接受服务,这样系统就多了10个进程,那么如果没有请求来的话这10个进程还在挂起状态,严重的浪费了系统的资源, 所以人们就想用一个进程来做,所以就出来了个inetd服务器的东西,就是说它读取/etc/inetd.conf文件读取10个进程的服务项,然后创建socket等等,这样系统中只是一个进程在挂起,来请求时,就调用相应的任务进程即可,这样节省了系统的资源。到目前为止,我们已经对 puma 是如何处理 http 请求的有一个比较清晰的认识了,对于每一个 http 请求都会由操作系统选择不同的进程来处理,这部分的负载均衡完全是由 os 层来做的,当请求被分配给某一个进程时,当前进程会根据持有的线程数选择是否对请求进行处理,在这时可能会创建新的 thread 对象来处理这个请求,也可能会把当前请求暂时扔到 reactor 中进行等待。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-113998-1.html
战前北洋水师已经十年没有更新舰艇了