这个问题很简单,解决的方法自然也很多。有些人喜欢一心一意的做某件事情,在做完一件事后,再做另外一件事情,这是典型的串行化思维。另外一些人喜欢两件事情同时做,做点A,碰到难题了,做点B,调节一下,再回过去做B。还有一些人情商比较高,门路广,兄弟多,事情自己做一点,另外的事情全部交给兄弟去做就可以了。
计算机是人发明的,在让计算机并行处理数据的思路上,碰到的问题和解决的方式同上面的情况相比并没有太大的区别。抢占式操作系统按时间片来分配线程的时间,对于操作系统而言(其本身也是一个进程),任何进程或线程都是其业务,必须同时进行。这毫无疑问相当于一个人同时做n件事情。使用单线程完成一个多任务的操作,类似于人们串行做n件事情。剩下的,多线程作业则像把事情交给多个人同时完成。
// 线程 HANDLE WINAPI CreateThread( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ SIZE_T dwStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD lpThreadId); BOOL WINAPI CloseHandle(_In_ HANDLE hObject); // 等待锁 WINBASEAPI DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds); WINBASEAPI DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds); // 互斥量 WINBASEAPI BOOL WINAPI InitializeCriticalSection( __out LPCRITICAL_SECTION lpCriticalSection); WINBASEAPI VOID WINAPI EnterCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection); WINBASEAPI VOID WINAPI LeaveCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection); WINBASEAPI VOID WINAPI DeleteCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection); WINBASEAPI __out HANDLE WINAPI CreateMutexA( __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes, __in BOOL bInitialOwner, __in_opt LPCSTR lpName); BOOL WINAPI ReleaseMutex( _In_ HANDLE hMutex); // 事件 HANDLE WINAPI CreateEvent( _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, _In_ BOOL bManualReset, _In_ BOOL bInitialState, _In_opt_ LPCTSTR lpName); BOOL WINAPI ResetEvent( _In_ HANDLE hEvent); BOOL WINAPI SetEvent( _In_ HANDLE hEvent); // 信号量 WINBASEAPI __out HANDLE WINAPI CreateSemaphore( __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, __in LONG lInitialCount, __in LONG lMaximumCount, __in_opt LPCSTR lpName); BOOL WINAPI ReleaseSemaphore( _In_ HANDLE hSemaphore, _In_ LONG lReleaseCount, _Out_opt_ LPLONG lpPreviousCount);
// 线程 int pthread_create( pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg); void pthread_exit(void *retval); int pthread_join(pthread_t th, void **thread_return); int pthread_detach(pthread_t th); // 互斥量 int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); // 条件变量 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); // 信号灯 int sem_post(sem_t * sem); int sem_wait(sem_t * sem); int sem_trywait(sem_t * sem);
type __sync_fetch_and_add (type *ptr, type value, ...) type __sync_fetch_and_sub (type *ptr, type value, ...) type __sync_fetch_and_or (type *ptr, type value, ...) type __sync_fetch_and_and (type *ptr, type value, ...) type __sync_fetch_and_xor (type *ptr, type value, ...) type __sync_fetch_and_nand (type *ptr, type value, ...) type __sync_add_and_fetch (type *ptr, type value, ...) type __sync_sub_and_fetch (type *ptr, type value, ...) type __sync_or_and_fetch (type *ptr, type value, ...) type __sync_and_and_fetch (type *ptr, type value, ...) type __sync_xor_and_fetch (type *ptr, type value, ...) type __sync_nand_and_fetch (type *ptr, type value, ...) // ...
LONG__cdecl InterlockedIncrement(LONG volatile* Addend); LONG__cdecl InterlockedDecrement(LONG volatile* Addend); LONG __cdecl InterlockedExchange(LONG volatile *Target, LONG Value); LONG__cdec InterlockedExchangeAdd(LONG volatile* Addend, LONGValue); // ...
读写锁与互斥量相似,不过读写锁允许更高的并行性,主要用于有很多读操作和很少写操作的情况。读写锁有三种状态:读模式加锁,写模式加锁,不加锁。读写锁可以通过两个信号量和一个互斥锁来实现。互斥量用来维护读操作的个数,两个信号量,一个用于标志无读用户事件发生,一个用于标志无写事件发生。
读写锁通常都用在读操作远远大于写操作的情况下,写的操作越少、单个写操作的时间越短,读写锁效率越高。读写锁的重心是读,并行的读操作,效率必须高。
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
spin_lock(&mr_lock); spin_unlock(&mr_lock);
减小锁的请求频率,通常的方法是分拆锁和分离锁。对于相互独立的状态变量,必须使用独立的锁进行保护。在拆分一个大锁的时候,要注意拆分时的力度,防止死锁和设计变得过于复杂。
有时候,把一个大锁分拆成为小锁时。如果不增加锁的数目,而只优化锁的流程,在把一个流程分段锁定后,会发现数据锁的碰撞变多,但单个锁定时间变少的情况。在这种情况下,需要进行具体分析,看锁的平均的等待时间是否变短。
由于读写锁的重点是读操作,优化读写锁时,读操作的平均等待时间可能要比写操作等待时间显得更重要。
一种高效无锁内存队列的实现 -- 无锁的应用
最快线程间数据交换算法,有效避免锁竞争 -- TwoQueues -- 如何分解和优化锁/读写锁优化/用copy操作缩小锁时间设计不使用互斥锁的并发数据结构 -- 如何分解和优化锁
Yet another implementation of a lock-free circular array queue
借shared_ptr实现copy-on-write -- 用copy操作缩小锁时间
并发编程的 15 条建议(译) -- 设计时的一些原则
多核编程中的线程随机竞争模式的概率分析 -- 对于热点的分析
Double Checked Locking 模式 -- double check的使用思考
Posix线程编程指南
(版权所有,转载时请注明作者和出处 http://blog.csdn.net/arau_sh/article/details/9080559)