对比:Linux和Windows系统线程间

熟悉WIN32编程的人一定知道,WIN32的进程管理方式与Linux上有着很大区别,在UNIX里,只有进程的概念,但在WIN32里却还有一个"线程"的概念,那么Linux和WIN32在这里究竟有着什么区别呢?

 

WIN32里的进程/线程是继承自OS/2的。在WIN32里,"进程"是指一个程序,而"线程"是一个"进程"里的一个执行"线索"。从核心上讲, WIN32的多进程与Linux并无多大的区别,在WIN32里的线程才相当于Linux的进程,是一个实际正在执行的代码。但是,WIN32里同一个进程里各个线程之间是共享数据段的。这才是与Linux的进程最大的不同。

 

下面这段程序显示了WIN32下一个进程如何启动一个线程。

 

 

int g; 
DWORD WINAPI ChildProcess( LPVOID lpParameter ){ 
int i; 
for ( i = 1; i <1000; i ++) { 
g ++; 
printf( "This is Child Thread: %d/n", g ); 
} 
ExitThread( 0 ); 
}; 

void main() 
{ 
int threadID; 
int i; 
g = 0; 
CreateThread( NULL, 0, ChildProcess, NULL, 0, &threadID ); 
for ( i = 1; i <1000; i ++) { 
g ++; 
printf( "This is Parent Thread: %d/n", g ); 
} 
}

 

在WIN32下,使用CreateThread函数创建线程,与Linux下创建进程不同,WIN32线程不是从创建处开始运行的,而是由 CreateThread指定一个函数,线程就从那个函数处开始运行。此程序同前面的UNIX程序一样,由两个线程各打印1000条信息。 threadID是子线程的线程号,另外,全局变量g是子线程与父线程共享的,这就是与Linux最大的不同之处。大家可以看出,WIN32的进程/线程要比Linux复杂,在Linux要实现类似WIN32的线程并不难,只要fork以后,让子进程调用ThreadProc函数,并且为全局变量开设共享数据区就行了,但在WIN32下就无法实现类似fork的功能了。所以现在WIN32下的C语言编译器所提供的库函数虽然已经能兼容大多数Linux/UNIX的库函数,但却仍无法实现fork。

 

对于多任务系统,共享数据区是必要的,但也是一个容易引起混乱的问题,在WIN32下,一个程序员很容易忘记线程之间的数据是共享的这一情况,一个线程修改过一个变量后,另一个线程却又修改了它,结果引起程序出问题。但在Linux下,由于变量本来并不共享,而由程序员来显式地指定要共享的数据,使程序变得更清晰与安全。

 

至于WIN32的"进程"概念,其含义则是"应用程序",也就是相当于UNIX下的exec了。

 

来源:http://www.souzz.net/html/server/Linux/40717.html

 

Windows与Solaris互斥与同步机制对比

 

韩三普

在Windows和Solaris中都提供进程与线程的互斥与同步机制。Windows提供了互斥对象、信号量对象和事件对象等三种内核同步对象和相应的系统调用 ,用于进程和线程同步。这些同步对象都有一个用户指定的对象名称,不同进程中用同样的对象名称来创建或打开对象,从而获得该对象在本进程的句柄。而Solaris也相应的提供了几个互斥同步对象,互斥锁(Mutex Locks),读写锁(Reader/writer (RW) locks),调度锁(Dispatcher Locks),和信号量(Semaphores)。下面将一一对比或者说明。

1互斥对象(Mutex)
Windows中的互斥对象(Mutex)就是互斥信号量,在一个时刻只能被一个线程使用。它的相关API包括:CreateMutex、OpenMutex和ReleaseMutex 。

a) CreateMutex创建一个互斥对象,返回对象句柄。

b) OpenMutex打开并返回一个已存在的互斥对象句柄,用于后续访问。

c) ReleaseMutex释放对互斥对象的占用,使之成为可用。

在Solaris中,有Mutex locks(可称做互斥锁)和Windows中的互斥对象有相似的地方又有所不同,相比更加复杂。一个线程得到一个互斥锁,就有两种可能,一是自旋(spin),调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁。另一情况是(block)阻塞,线程被安排在一个睡眠队列中,当锁被释放会发出信号给线程。自旋的好处是没有上下文切换的开销,效率非常高。而阻塞的优势是可以释放CPU给其它线程,但是需要上下文环境,并且比自旋锁效率低一点。由此系统为Mutex提供了两种锁,自旋锁和自适应锁。自旋锁就是采用自旋的方式,而自适应锁是根据持有者的状态,动态平衡是否采用自旋或者阻塞;如果锁的持有者在运行态,线程得到的锁就会是自旋的,如果不在运行态,就会是阻塞的,这样充分发挥了两种锁的优点。

下面是Solaris提供的mutex locks的实现函数:

a) mutex_init(): 初始化一个锁,只能选择初始自旋或者自适应两种的一种,默认是自适应。

b) mutex_enter():获取互斥锁

c) mutex_vector_enter(): 当锁被持有或者是自旋时获取互斥锁

d) mutex_exit(): 释放一个锁

2信号量对象(Semaphore)
Windows中信号量对象(Semaphore)就是资源信号量,取值的取值在0到指定最大值之间,用于限制并发访问的线程数。它的相关API包括:CreateSemaphore、OpenSemaphore和ReleaseSemaphore

a) CreateSemaphore创建一个信号量对象,在输入参数中指定最大值和初值,返回对象句柄

b) OpenSemaphore返回一个已存在的信号量对象的句柄,用于后续访问

c) ReleaseSemaphore释放对信号量对象的占用

在Solaris中,内核也提供了信号量(Semaphores),可同步的使用可共享的资源。可对它进行P、V操作。P操作尝试得到一个信号量,V操作释放一个信号量。根据共享资源的数量初始化信号量的值。其原理和windows非常相似。

下面是Solaris提供的semaphores的实现函数:

a) sema_init(): 初始化信号量

b) sema_p(): P操作,尝试获取信号量

c) sema_v(): V操作,释放信号量

d) sema_held(): 测试函数

e) sema_destroy(): 销毁信号量

3事件对象(Event)
Windows提供的另一个互斥与同步对象是事件对象(Event),相当于“触发器”,可用于通知一个或多个线程某事件的出现。它的相关的API包括:CreateEvent、OpenEvent、SetEvent、ResetEvent和PulseEvent

a) CreateEvent创建一个事件对象,返回对象句柄

b) OpenEvent返回一个已存在的事件对象的句柄,用于后续访问

c) SetEvent和PulseEvent设置指定事件对象为可用状态

d) ResetEvent设置指定事件对象为不可用状态

4临界区对象(Critical Section)
这是Windows环境提供的又一种同步互斥机制。只能在同一进程内使用的临界区,同一进程内各线程对它的访问是互斥进行的。把变量说明为CRITICAL_SECTION类型,就可作为临界区使用。有关的API:

a) InitializeCriticalSection对临界区对象进行初始化;

b) EnterCriticalSection等待占用临界区的使用权,得到使用权时返回;

c) TryEnterCriticalSection非等待方式申请临界区的使用权;申请失败时,返回0;

d) LeaveCriticalSection释放临界区的使用权;

e) DeleteCriticalSection释放与临界区对象相关的所有系统资源;

5互锁变量访问
在Windows下,还可以采用互锁变量访问的方法实现同步互斥,它相当于硬件指令,对一个整数(进程内的变量或进程间的共享变量)进行操作。其目的是避免线程间切换的影响。有关的API:

a) InterlockedExchange进行32位数据的先读后写原子操作;

b) InterlockedCompareExchange依据比较结果进行赋值的原子操作;

c) InterlockedExchangeAdd先加后存结果的原子操作;

d) InterlockedDecrement先减1后存结果的原子操作;

e) InterlockedIncrement先加1后存结果的原子操作;

6调度锁(Dispatcher Locks)
另外,在Solaris中还有一种锁,可支持多CPU调度,叫做调度锁(Dispatcher Locks)。内核的分配器Kernel dispatcher 查看线程的上下文环境来控制分配队列它分为两种类型,分别是普通的自旋锁和CPU优先权提升的锁。

7读写锁(Reader/Writer Locks)
这也是Solaris提供的一种互斥同步机制,它适用于读者写者问题。比如:可在多线程同时读取数据,只有一个线程写数据时用到。如果有一个写用户得到这个锁,所有读用户都不可以访问。

基本实现方法:

a) rw_init(): 初始化读写锁。

b) rw_enter():得到读写锁

c) rw_exit(): 释放读写锁

 

来源:http://www.linuxdiyf.com/viewarticle.php?id=95746

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值