lecture21_thread1

63
COMP 150-CCP COMP 150-CCP Concurrent Programming Concurrent Programming Lecture 21: Concurrency in Other Environments (Part 1) Dr. Richard S. Hall [email protected] Clement Escoffier [email protected] Concurrent programming – April 8th, 2008

Upload: rishisharma

Post on 16-Jan-2016

213 views

Category:

Documents


0 download

DESCRIPTION

Lecture21_thread1

TRANSCRIPT

Page 1: Lecture21_thread1

COMP 150-CCPCOMP 150-CCPConcurrent ProgrammingConcurrent Programming

Lecture 21:Concurrency in Other Environments (Part 1)

Dr. Richard S. Hall [email protected]

Clement [email protected]

Concurrent programming – April 8th, 2008

Page 2: Lecture21_thread1

Why Use Java for the Course?Why Use Java for the Course?

Java is widely popular Java treats concurrency as a first-class concept

It is not tacked on as an afterthought It is reasonably simple to use the concurrency

mechanisms without having to deal with extra cruft

Java is available and works well across many platforms

Makes it accessible to students on their preferred computing environment

Page 3: Lecture21_thread1

Why Not Java?Why Not Java?

Java is not suited to all tasks Other approaches are potentially more innovative

(e.g., Erlang)( Other languages are popular (e.g., C/C++)O Other platforms are popular (e.g., Linux,

Win32, .NET)W

The last two bullets will be the focus of this lecture to provide some perspective

Page 4: Lecture21_thread1

AgendaAgenda

Linux, C/C++, and Pthreads Win32 and C/C++ .NET and C#

Page 5: Lecture21_thread1

AgendaAgenda

Linux, C/C++, and PthreadsDerived from

https://computing.llnl.gov/tutorials/pthreads/

Page 6: Lecture21_thread1

What are Pthreads?What are Pthreads?

Different platforms have their own proprietary versions of threads

Implementations differed substantially making it difficult to develop portable threaded application

A standardized threading API was required For UNIX-based systems, this interface has been

specified by the IEEE POSIX 1003.1c threads standard (aka Pthreads))

▴ A set of C language programming types and procedure calls

Page 7: Lecture21_thread1

Pthreads RecommendationPthreads Recommendation

Be careful if your application uses libraries or other objects that do not explicitly guarantee thread safety

When in doubt, assume that they are not thread-safe until proven otherwise

This can be done by serializing the calls to the uncertain routine

Page 8: Lecture21_thread1

Pthreads OverviewPthreads Overview

The subroutines which comprise the Pthreads API can be grouped into three major classes

Thread management▴ These functions work directly on threads▴ e.g., creating, detaching, and joining threads

Mutex management▴ These functions deal with synchronization▴ e.g., creating, destroying, locking and unlocking mutex locks

Condition variables▴ These functions address communication between threads

based on programmer specified conditions▴ e.g., creating, destroying, waiting and signaling condition

variables

Page 9: Lecture21_thread1

Pthreads API Overview (1/2)Pthreads API Overview (1/2)PP

All library identifiers begin with pthread_ Common prefixes

▴ pthread_ - for threads themselves▴ pthread_attr_ - for thread attributes▴ pthread_mutex_ - for mutexes▴ pthread_mutexattr_ - for mutex attributes▴ pthread_cond_ - for condition variables▴ pthread_condattr_ - for condition variable attributes▴ pthread_key_ - for thread-specific data keys

We will concentrate on threads, mutexes, and condition variables

Page 10: Lecture21_thread1

Pthreads API Overview (2/2)Pthreads API Overview (2/2)PP

Pthreads API is centered around the concept of opaque objects

The basic calls create or modify opaque objects

Pthreads API typically requires both resource creation and destruction to handle resource allocation

No garbage collector here

The Pthreads API contains over 60 subroutines The current POSIX standard is defined only for

the C language

Page 11: Lecture21_thread1

Linux Development with PthreadsLinux Development with Pthreads

Include pthread.h in your source

Compile using “g++ -pthread”

Page 12: Lecture21_thread1

Pthreads Thread APIPthreads Thread API

int pthread_create( pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void*), void *restrict arg);

int pthread_attr_init(pthread_attr_t *attr);

int pthread_attr_destroy(pthread_attr_t *attr);

int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate);

int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate);

int pthread_join(pthread_t thread, void **value_ptr);

int pthread_detach(pthread_t thread);

void pthread_exit(void *value_ptr);

Page 13: Lecture21_thread1

Thread CreationThread Creation

pthread_create(thread,attr,start_routine,arg)p

Thread type: pthread_t Creates a new thread

Can create any number of new threads Created threads are peers in a given process

Arguments thread - opaque, unique thread identifier attr - opaque object for setting thread attributes start_routine - routine for the thread to execute arg - argument passed to the start routine

Page 14: Lecture21_thread1

Thread AttributesThread Attributes

pthread_attr_init(attr);

pthread_attr_destroy(attr);

pthread_attr_getdetachstate(attr,detachstate);

pthread_attr_setdetachstate(attr,detachstate);

Create, set, get, and destroy thread attributes One specific attribute is whether a thread

joinable or detached Detached threads can never be joined Resources for joinable threads are freed when joined

Good practice to specifically create your threads as either joinable or detached

pthread_detach can detach a joinable thread

Page 15: Lecture21_thread1

Thread TerminationThread Termination

pthread_exit(status);

Stops a thread Called when a thread is no longer needed Does not clean up resources Also needed in main() if it exits before threads

pthread_join(threadid,status);

Allows the calling thread to wait for the specified thread to exit

Retrieves the exit status from the exiting thread

Page 16: Lecture21_thread1

Simple Thread Example (1/2)Simple Thread Example (1/2)SS

#include <pthread.h>#include <stdio.h>#include <stdlib.h>#define NUM_THREADS 3

// Routine for our threadsvoid *BusyWork(void *null) { int i; double result=0.0; // Perform busy work. for (i=0; i<1000000; i++) { result = result + (double)random(); } printf("result = %e\n",result); // Terminate the thread. pthread_exit((void *) 0);}

// Continued on next slide...

Page 17: Lecture21_thread1

Simple Thread Example (2/2)Simple Thread Example (2/2)SS

int main () { pthread_t thread[NUM_THREADS]; pthread_attr_t attr; int t; void *status; // Create thread joinable attribute. pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // Create the threads. for(t = 0; t < NUM_THREADS; t++) { printf("Creating thread %d\n", t); pthread_create(&thread[t], &attr, BusyWork, NULL); } // Destroy the attribute. pthread_attr_destroy(&attr); // Join all threads and print exit status. for(t = 0; t < NUM_THREADS; t++) { pthread_join(thread[t], &status); printf("Thread %d exit status = %ld\n", t, (long)status); } // Terminate main thread. pthread_exit(NULL);}

Page 18: Lecture21_thread1

Miscellaneous Thread APIMiscellaneous Thread API

pthread_self()p Returns the identifier of the calling thread

pthread_equal(thread1,thread2)p Determines if two threads are equal

pthread_yield()p Forces the calling thread to give up the processor

Page 19: Lecture21_thread1

Pthreads Mutex APIPthreads Mutex API

int pthread_mutex_init( pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

int pthread_mutexattr_init(pthread_mutexattr_t *attr);

int pthread_mutexattr_destroy( pthread_mutexattr_t *attr);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

Page 20: Lecture21_thread1

Mutex CreationMutex Creation

pthread_mutex_init(mutex,attr)p

Mutex type: pthread_mutex_t Mutexes are created in unlocked state Mutex attributes can control various properties,

but we don't explore these

Page 21: Lecture21_thread1

Mutex Locking and UnlockingMutex Locking and Unlocking

pthread_mutex_lock(mutex);pthread_mutex_trylock(mutex);pthread_mutex_unlock(mutex);

Lock, test a lock, and unlock mutexes Mutexes are not reentrant

Trying to acquire a lock twice will deadlock

Mutexes are not magical, they are just an agreement between threads

If a thread doesn't use them, then all bets are off

Page 22: Lecture21_thread1

Simple Mutex Example (1/2)Simple Mutex Example (1/2)SS

#include <pthread.h>#include <stdio.h>#include <stdlib.h>#define NUM_THREADS 3#define NUM_INCREMENTS 100

int shared; pthread_mutex_t mutex;

void *BusyWork(void *null) { int tmp; for (int i = 0; i < 100; i++) { // Lock. pthread_mutex_lock(&mutex); tmp = shared; tmp++; pthread_yield(); shared = tmp; // Unlock. pthread_mutex_unlock(&mutex); } // Terminate thread. pthread_exit((void *) 0);}// Continued on next slide...

Page 23: Lecture21_thread1

Simple Mutex Example (2/2)Simple Mutex Example (2/2)SS

int main () { pthread_t thread[NUM_THREADS]; pthread_attr_t attr; // Create mutex. pthread_mutex_init(&mutex, NULL); // Create thread joinable attribute. pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // Create the threads. for(int t = 0; t < NUM_THREADS; t++)f pthread_create(&thread[t], &attr, BusyWork, NULL); // Destroy the attribute. pthread_attr_destroy(&attr); // Join all threads. for(int t = 0; t < NUM_THREADS; t++)f pthread_join(thread[t], NULL); if (shared != (NUM_THREADS * NUM_INCREMENTS))i printf("Shared value is incorrect = %d\n", shared); // Destroy the mutex. pthread_mutex_destroy(&mutex); // Terminate main thread. pthread_exit(NULL);}

Page 24: Lecture21_thread1

Pthreads Condition Variable APIPthreads Condition Variable API

int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

int pthread_condattr_init(pthread_condattr_t *attr);

int pthread_condattr_destroy(pthread_condattr_t *attr);

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

int pthread_cond_timedwait( pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);

int pthread_cond_broadcast(pthread_cond_t *cond);

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_destroy(pthread_cond_t *cond);

Page 25: Lecture21_thread1

Condition Variable CreationCondition Variable Creation

pthread_cond_init(cond,attr);

Condition variable type: pthread_cond_t Condition variables allow threads to

communicate and wait for certain conditions Just like in Java

We don't explore condition variable attributes

Page 26: Lecture21_thread1

Condition Variable WaitingCondition Variable Waiting

pthread_cond_wait(cond,mutex);pthread_cond_timedwait(

cond,mutex,abstime);

Must specify the mutex associated with the condition variable when waiting

Must be called when mutex is locked by calling thread

Can wait indefinitely or for a certain amount of time

Similar to Java, you should wait in a loop in case of a spurious wake up

Page 27: Lecture21_thread1

Condition Variable SignalingCondition Variable Signaling

pthread_cond_signal(cond);pthread_cond_broadcast(cond);

Can signal a single thread or broadcast to all threads waiting on the condition variable

Must hold the lock to signal Should release the lock after signaling

Page 28: Lecture21_thread1

Bounded Buffer Example (1/7)Bounded Buffer Example (1/7)BB

#include <iostream>#include <string>#include <pthread.h>

using namespace std;

class BoundedBuffer {private: // Encapsulate mutex and condition // variable. pthread_mutex_t mutex; pthread_cond_t condvar; string *buffer; int max, in, out, count;

public: BoundedBuffer(int m); ~BoundedBuffer(); void put(string s); string get();};

Page 29: Lecture21_thread1

Bounded Buffer Example (2/7)Bounded Buffer Example (2/7)BB

BoundedBuffer::BoundedBuffer(int m) { max = m; buffer = new string[max]; in = out = count = 0; // Initialize mutex and condition variable. pthread_mutex_init(&mutex, NULL); pthread_cond_init(&condvar, NULL);}

BoundedBuffer::~BoundedBuffer() { // Destroy mutex and condition variable. pthread_mutex_destroy(&mutex); pthread_cond_destroy(&condvar);}

Page 30: Lecture21_thread1

Bounded Buffer Example (3/7)Bounded Buffer Example (3/7)BB

void BoundedBuffer::put(string s) { // Acquire lock. pthread_mutex_lock(&mutex); // Wait for there to be space. while (count == max) { pthread_cond_wait(&condvar, &mutex); }

cout << "PUT "; for (int i = 0; i < count; i++) { cout << " " << buffer[(i + out) % max] << " "; } cout << "[" << s << "]" << endl; buffer[in] = s; ++count; in = (in + 1) % max;

// Broadcast and unlock. pthread_cond_broadcast(&condvar); pthread_mutex_unlock(&mutex);}

Page 31: Lecture21_thread1

Bounded Buffer Example (4/7)Bounded Buffer Example (4/7)BB

string BoundedBuffer::get() { // Acquire lock. pthread_mutex_lock(&mutex); // Wait for data. while (count == 0) { pthread_cond_wait(&condvar, &mutex); }

string s = buffer[out]; buffer[out] = ""; --count; out = (out + 1) % max; cout << "GET [" << s << "] "; for (int i = 0; i < count; i++) { cout << buffer[(i + out) % max] << " "; } cout << endl;

// Broadcast and unlock. pthread_cond_broadcast(&condvar); pthread_mutex_unlock(&mutex); return s;}

Page 32: Lecture21_thread1

Bounded Buffer Example (5/7)Bounded Buffer Example (5/7)BB

// Produce items to consume.void * producer(void *v) { BoundedBuffer *pBuffer = (BoundedBuffer *) v; string alphabet = "abcdefghijklmnopqrstuvwxyz"; int ai = 0; while (true) { pBuffer->put(alphabet.substr(ai, 1)); ai = (ai + 1) % 26; usleep(1000); }}

Page 33: Lecture21_thread1

Bounded Buffer Example (6/7)Bounded Buffer Example (6/7)BB

// Consume produced items.void * consumer(void *v) { while (true) { BoundedBuffer *pBuffer = (BoundedBuffer *) v; string s = pBuffer->get(); usleep(1000); }}

Page 34: Lecture21_thread1

Bounded Buffer Example (7/7)Bounded Buffer Example (7/7)BB

int main() { // Create shared buffer. BoundedBuffer *pBuffer = new BoundedBuffer(5);

// Create detached thread attribute. pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

// Create producer and consumer threads. pthread_t p, c; pthread_create(&p, &attr, producer, pBuffer); pthread_create(&c, &attr, consumer, pBuffer);

// Destroy attribute. pthread_attr_destroy(&attr);

// Terminate main thread. pthread_exit(NULL);}

Page 35: Lecture21_thread1

Bounded Buffer IssueBounded Buffer Issue

No garbage collection in C/C++ makes some things more difficult

We would have to worry about freeing the allocated bounded buffer if the producer and consumer threads eventually terminate, but the program continues

▴ In Java we could just ignore this issue

Page 36: Lecture21_thread1

Pthreads & C++Pthreads & C++

The Pthreads API was designed for C; however, integrating it with C++ is reasonably straightforward

The next few slides present a simple “thread” class in C++

http://www.oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-18.html

Page 37: Lecture21_thread1

Thread Class DefinitionThread Class Definition

class Thread{ public: Thread(); int Start(void *arg); protected: int Run(void *arg); static void * EntryPoint(void*); virtual void Setup(); virtual void Execute(void*); void * Arg() const { return arg_; } void Arg(void* a) { arg_ = a; } private: pthread_t threadId_; void * arg_;};

Page 38: Lecture21_thread1

Thread Class ImplementationThread Class Implementation

Thread::Thread() {}

int Thread::Start(void *arg) { Arg(arg); // store user data int code = pthread_create( &threadId_, NULL, Thread::EntryPoint, this); return code;}

void * Thread::EntryPoint(void *pthis) { // static Thread * pthread = (Thread *) pthis; pthread->Run(Arg());}

int Thread::Run(void *arg) { Setup(); Execute(arg);}

virtual void Thread::Setup() { /* Override */ }

virtual void Thread::Execute(void *arg) { /* Override */ }

Page 39: Lecture21_thread1

Thread Class UsageThread Class Usage

Each object is for a single thread Thread does not exist until Start() is called

To use, create a subclass The Setup() method can be overloaded to perform

any setup before the thread runs The Execute() method must be overloaded to

perform the function of the thread

Notice that the thread requires a static function We get around this by passing in this as the

argument to the thread, which casts it back to the Thread object so that it can invoke Run()R

Page 40: Lecture21_thread1

Pthreads SummaryPthreads Summary

Pthreads gives us a portable threading API for UNIX-based systems

We only covered the basics in this lecture However, it is actually fairly simple and there isn't

much more

Pthreads is oriented toward C, but works reasonably well with C++

Page 41: Lecture21_thread1

AgendaAgenda

Win32 and C/C++

Page 42: Lecture21_thread1

Thread on WindowsThread on Windows

Very very useful Imagine a game without threads All Windows-based GUI use threads

Different thread libraries The old-fashion MFC (Microsoft Foundation Class) OpenThread (since Windows 98) New improvements in Vista

Page 43: Lecture21_thread1

Example of Threads in WindowsExample of Threads in Windows

The windows explorer example Threads can be viewed with “Process Explorer” One “Browse” Thread per Windows Explorer

windows

Page 44: Lecture21_thread1

Thread SchedulingThread Scheduling

Win32 threads are scheduled according to the round-robin principle

This includes multiprocessor machines Windows stays in control of how long each thread

gets executed

In a cycle, each thread gets allocated a ‘time slice’

Threads can have different priorities

Page 45: Lecture21_thread1

Thread System OverviewThread System Overview

The Win32 Thread API can be grouped into three major classes

Thread management▴ These functions work directly on threads▴ e.g., creating, detaching, and joining threads

Mutex management▴ These functions deal with synchronization▴ e.g., creating, destroying, locking and unlocking mutex locks

Condition variables▴ These functions address communication between threads

based on programmer specified conditions▴ e.g., creating, destroying, waiting and signaling condition

variables

Page 46: Lecture21_thread1

Thread LibraryThread Library

Header: include <windows.h>

It uses directly kernel32.h

Page 47: Lecture21_thread1

Thread CreationThread Creation

HANDLE CreateThread(__in LPSECURITY_ATTRIBUTES lpThreadAttributes,__in DWORD dwStackSize,__in LPTHREAD_START_ROUTINE lpStartAddress,__in LPVOID lpParameter,__in DWORD dwCreationFlags,__out LPDWORD lpThreadIdjl

);

Arguments lpThreadAttributes – Security parameter ... NULL dwStackSize – Stack Size, can be NULL (default size set by Windows) lpStartAddress – Function pointer on you Thread run method lpParameter - The parameter to be passed to the thread procedure DwCreationFlags - The creation flags (0 or CREATE_SUSPENDED). LpThreadIdjl - [out] Address of the DWORD variable that, on

success, receives the thread ID of the newly created thread

Page 48: Lecture21_thread1

Thread CreationThread Creation

Thread procedure Use a function pointer DWORD WINAPI ThreadProc( LPVOID

lpParameter );

Example of thread creationDWORD WINAPI ThreadProc(LPVOID lpParameter){

printf("This is my windows thread\n");}

int main(){DWORD threadID;CreateThread(NULL, 0, Thread1, NULL, 0, &threadID);Sleep(1000); // Avoid too fast terminationreturn 0;

}

Page 49: Lecture21_thread1

Thread Creation with AttributesThread Creation with Attributes

DWORD WINAPI Thread1(int param) {printf("This is my thread n° %i \n", param);

}

int main() {DWORD threadID1;DWORD threadID2;DWORD threadID3;DWORD threadID4;CreateThread(NULL, 0, Thread1, 1, 0, &threadID1);CreateThread(NULL, 0, Thread1, 2, 0, &threadID2);CreateThread(NULL, 0, Thread1, 3, 0, &threadID3);CreateThread(NULL, 0, Thread1, 4, 0, &threadID4);Sleep(1000);return 0;

}

Page 50: Lecture21_thread1

Stopping/Resuming ThreadsStopping/Resuming Threads

Function to stop the calling threadVOID WINAPI ExitThread( __in DWORD dwExitCode);

However, must be used carefully: The thread is exited before any destructors can be called or any other automatic

cleanup can be performed. Therefore, you should return from your thread function.

Function to resume a threadDWORD WINAPI ResumeThread(

__in HANDLE hThread);

Decrements a thread's suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed.

Function to suspend a threadDWORD WINAPI ResumeThread(

__in HANDLE hThread);

Page 51: Lecture21_thread1

Thread SynchronizationThread Synchronization

How to synchronized our threads: Events Mutexes Semaphores Critical Sections Condition Variables

Page 52: Lecture21_thread1

Using EventsUsing Events

A thread wait for an event launched by another thread Allow to remove the sleep call

Create an event :HANDLE CreateEvent( __in LPSECURITY_ATTRIBUTES lpEventAttributes, // SD __in BOOL bManualReset, // reset type __in BOOL bInitialState, // initial state __in LPCTSTR lpName // object name);

Wait for an eventDWORD WaitForSingleObject( __in HANDLE hHandle, // handle to object __in DWORD dwMilliseconds // time-out interval);

Page 53: Lecture21_thread1

Using EventsUsing Events

Signal event (becomes signaled):BOOL SetEvent( __in HANDLE hEvent // handle to event);

“Unsignal” event: BOOL ResetEvent( __in HANDLE hEvent // handle to event);

Others wait functions WaitForSingleObject(), WaitForMultipleObjects(),

SignalObjectAndWait(), WaitForMultipleObjectsEx()S MsgWaitForMultipleObjects(), MsgWaitForMultipleObjectsEx,

MsgWaitForMultipleObjectsEx(), SignalObjectAndWait(), WaitForMultipleObjectsEx(), WaitForSingleObjectEx()W RegisterWaitForSingleObject()R

Page 54: Lecture21_thread1

Using EventsUsing Events

HANDLE g_event;

DWORD WINAPI ThreadProc(LPVOID lpParameter) {

printf("This is my thread\n");

SetEvent(g_event); // Once done set the event to signaled

}

int main() {

g_event=CreateEvent(NULL, 0, 0, NULL); // Create the event

DWORD threadID;

CreateThread(NULL, 0, Thread1, NULL, 0, &threadID);

WaitForSingleObject(g_event, INFINITE); // Wait for the event

return 0;

}

Page 55: Lecture21_thread1

Using Mutex ObjectsUsing Mutex Objects

Protect a shared resource from simultaneous access by multiple threads or processes.

Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource.

HANDLE WINAPI CreateMutex( __in LPSECURITY_ATTRIBUTES lpMutexAttributes, __in BOOL bInitialOwner, __in_opt LPCTSTR lpName )

Getting the mutex by waiting for an event with WaitForSingleObject

Releasing a mutex withBOOL WINAPI ReleaseMutex(

__in HANDLE hMutex )

Page 56: Lecture21_thread1

Using Mutex ObjectsUsing Mutex Objects

Main// Create a mutex with no initial owner

ghMutex = CreateMutex(

NULL, // default security attributes

FALSE, // initially not owned

NULL); // unnamed mutex );

In the thread procedure:dwWaitResult = WaitForSingleObject(

ghMutex, // handle to mutex

INFINITE); // no time-out interval

// Do something

ReleaseMutex(ghMutex)

Page 57: Lecture21_thread1

Using SemaphoresUsing Semaphores

Very close to mutexesghSemaphore = CreateSemaphore(

NULL, // default security attributes

MAX_SEM_COUNT, // initial count

MAX_SEM_COUNT, // maximum count

NULL); // unnamed semaphore

dwWaitResult = WaitForSingleObject(

ghSemaphore, // handle to semaphore

INFINITE); // zero-second time-out interval

ReleaseSemaphore(

ghSemaphore, // handle to semaphore

1, // increase count by one

NULL) ) // not interested in previous count (out)

Page 58: Lecture21_thread1

Using Critical SectionsUsing Critical Sections

Define a critical section by giving the entry address (pointer)InitializeCriticalSectionAndSpinCount(

&CriticalSection, //Pointer on the critical sections

0) // Spin count (0 on mono-processor)... // Release resources used by the critical section object. DeleteCriticalSection(&CriticalSection)

Then call entry and exit functions// Request ownership of the critical section. EnterCriticalSection(&CriticalSection);

// Access the shared resource.

// Release ownership of the critical section. LeaveCriticalSection(&CriticalSection);

Page 59: Lecture21_thread1

Condition VariablesCondition Variables

Same semantic as in Java or Pthreads Four main functions

InitializeConditionVariable ▴ Initializes a condition variable.

SleepConidtionVariableCS ▴ Sleeps on the specified condition variable and releases the

specified critical section as an atomic operation. SleepConditionVariableSRW

▴ Sleeps on the specified condition variable and releases the specified SRW lock as an atomic operation.

WakeAllConditionVariable ▴ Wakes all threads waiting on the specified condition variable.

WakeConditionVariable▴ Wakes a single thread waiting on the specified condition variable.

Page 60: Lecture21_thread1

Condition VariablesCondition Variables

The producer/consumer exampleEnterCriticalSection (&BufferLock);

while (QueueSize == BUFFER_SIZE && StopRequested == FALSE){

// Buffer is full - sleep so consumers can get items.

SleepConditionVariableCS (

&BufferNotFull, &BufferLock, INFINITE);

}

if (StopRequested == TRUE) {

LeaveCriticalSection (&BufferLock);

return; }

// Add the produced element …

WakeConditionVariable (&BufferNotEmpty);

LeaveCriticalSection (&BufferLock);

}

Page 61: Lecture21_thread1

Other Synchronization MechanismsOther Synchronization Mechanisms

Waitable timer objects Waitable timers with an asynchronous procedure

call One-time initialization Using timer queues Atomic Actions

Page 62: Lecture21_thread1

Win32 Threads IssuesWin32 Threads Issues

No garbage collection in C/C++ makes some things more difficult

Complex to use Do not forget to clean threads :

▴ All threads need to be stopped “nicely”▴ All handles need to be closed

Page 63: Lecture21_thread1

ConclusionConclusion

Threads are by default supported in Win32 However, it exists others library

MFC (Microsoft Foundation Class) OpenThread (Close to Java thread)

To go further : MSDN : http://msdn.com