SDL2新手入门 —— 多线程与线程同步

SDL2 阅读(182)

# 多线程与线程同步  
SDL线程函数的函数原型 :  
```C
int SDL_ThreadFunction(void* data);
```

使用[`SDL_CreateThread`](http://wiki.libsdl.org/SDL_CreateThread)函数创建线程 :  
```C
#include <SDL_thread.h>
SDL_Thread* SDL_CreateThread(SDL_ThreadFunction fn,const char* name,void* data);
//成功返回线程指针,失败返回NULL
```
* `fn`参数是线程函数
* `name`参数是线程名称
* `data`参数是传给`fn`的任意参数

使用[`SDL_WaitThread`](http://wiki.libsdl.org/SDL_WaitThread)函数阻塞等待线程结束 :  
```C
#include <SDL_thread.h>
void SDL_WaitThread(SDL_Thread* thread,int* status);
```
* `thread`参数是等等的线程
* `status`参数**返回**线程的退出状态

为了线程安全,当多个线程要读写同一个数据时,需要进行线程同步。SDL2提供互斥量(Mutex)来完成这个操作。  
[`SDL_CreateMutex`](http://wiki.libsdl.org/SDL_CreateMutex)函数创建一个互斥量,[`SDL_DestroyMutex`](http://wiki.libsdl.org/SDL_DestroyMutex)函数销毁一个互斥量。  
```C
#include <SDL_mutex.h>
SDL_mutex* SDL_CreateMutex(void);
//成功返回互斥量指针,失败返回NULL
 
void SDL_DestroyMutex(SDL_mutex* mutex);
```

[`SDL_LockMutex`](http://wiki.libsdl.org/SDL_LockMutex)函数锁定一个互斥量,如果该互斥量已经被其他代码上锁,则阻塞到其解锁后再锁定。  
[`SDL_TryLockMutex`](http://wiki.libsdl.org/SDL_TryLockMutex)函数尝试锁定一个互斥量,如果该互斥量已经被其他代码上锁,不阻塞。  
[`SDL_UnlockMutex`](http://wiki.libsdl.org/SDL_UnlockMutex)函数解锁一个互斥量。  
```C
#include <SDL_mutex.h>
int SDL_LockMutex(SDL_mutex* mutex);
//成功返回0,失败返回非0
 
int SDL_UnlockMutex(SDL_mutex* mutex);
//成功返回0,失败返回非0
 
int SDL_TryLockMutex(SDL_mutex* mutex);
//成功返回0,失败返回-1,互斥量已被上锁返回SDL_MUTEX_TIMEDOUT
```

## 一个完整的线程使用示例代码
```C
 
int draw(void* renderer);//绘图线程函数
int control(void* data);//控制线程函数
void move(SDL_Keycode direction,SDL_Rect* r);//移动方块
 
SDL_Rect rect = {0,0,100,100};//正方形,由于两个线程都要操作它,因此需要互斥量
SDL_mutex* mutex = NULL;//互斥量
char isrun = 1;
 
int main(int argc,char* argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window* window = SDL_CreateWindow("SDL2",SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,640,400,0);
    SDL_Renderer* renderer = SDL_CreateRenderer(window,-1,
                                    SDL_RENDERER_ACCELERATED);
 
 
    mutex = SDL_CreateMutex();//创建互斥量
    /* 实际上可以把下面两个线程中的一个放在main中 */
    SDL_Thread* dThread = SDL_CreateThread(draw,"draw",renderer);//创建绘图线程
    SDL_Thread* cThread = SDL_CreateThread(control,"control",NULL);//创建控制线程
    SDL_WaitThread(dThread,NULL);//等待线程结束
    SDL_WaitThread(cThread,NULL);
    SDL_DestroyMutex(mutex);//销毁互斥量
 
 
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
     
     
    return 0;
}
 
 
int draw(void* renderer)
{
    while(isrun)//isrun控制线程结束
    {
        SDL_SetRenderDrawColor(renderer,0,0,0,0);
        SDL_RenderClear(renderer);
        SDL_SetRenderDrawColor(renderer,0,0xff,0,0);
        if(SDL_LockMutex(mutex) == 0)//互斥量上锁
        {
            SDL_RenderFillRect(renderer,&rect);
            SDL_UnlockMutex(mutex);//互斥量解锁
        }
        SDL_RenderPresent(renderer);
    }
    return 0;
}
 
 
 
int control(void* data)
{
    SDL_Event e;
    while(1)
    {
        if(SDL_WaitEvent(&e) == 0)
        {
            continue;
        }
        else if(e.type == SDL_QUIT)
        {
            isrun = 0;//让绘图线程结束
            return 0;//结束控制线程
        }
        else if(e.type == SDL_KEYDOWN)
        {
            if(SDL_LockMutex(mutex) == 0)//互斥量上锁
            {
                move(e.key.keysym.sym,&rect);//移动正方形
                SDL_UnlockMutex(mutex);//互斥量解锁
            }
        }
    }
    return 0;
}
 
 
void move(SDL_Keycode direction,SDL_Rect* r)
{
    switch(direction)
    {
        case SDLK_LEFT  : r->x -= 5;break;
        case SDLK_RIGHT : r->x += 5;break;
        case SDLK_UP    : r->y -= 5;break;
        case SDLK_DOWN  : r->y += 5;break;
        default: return;
    }
}
```

Markdown使用 帮助


匿名

爆ぜろリアル  弾けろシナプス   バニッシュメント・ディス・ワールド!

匿名

富强 民主 文明 和谐 自由 平等 公正 法治 爱国 敬业 诚信 友善

匿名

富强 民主 文明 和谐 自由 平等 公正 法治 爱国 敬业 诚信 友善

匿名

我有一头小毛驴,我从来也不骑。