2012-12-20 218 views
3

我目前正在开始使用Allegro跨平台库在C上进行独立游戏开发。我想我会将诸如输入,声音,游戏引擎和图形之类的东西分离到各自的线程中,以提高程序的稳健性。没有多线程的经验,我的问题是:多线程和互斥锁

如果我在内存中有一段数据(比如指向数据结构的指针),一个线程可以随意写入,从中随意读取,还是每个线程都必须使用互斥锁来锁定内存,然后读取或写入,然后解锁?

特别是,我在考虑游戏引擎和视频渲染器之间的交互。 (这是2D格式。)我的计划是让引擎处理用户输入,然后吐出合适的音频和视频,送到扬声器和监视器。我在想,我有一个全球性的指针到下一个位图在屏幕上绘制,并为游戏引擎和渲染器的代码将是这样的:

ALLEGRO_BITMAP *nextBitmap; 
boolean using; 

void GameEngine() 
    { 

    ALLEGRO_BITMAP *oldBitmap; 

    while (ContinueGameEngine()) 
    { 
    ALLEGRO_BITMAP *bitmap = al_create_bitmap (width, height); 
    MakeTheBitmap (bitmap); 
    while (using) ; //The other thread is using the bitmap. Don't mess with it! 
    al_destroy_bitmap (nextBitmap); 
    nextBitmap = bitmap; 
    } 

    } 

void Renderer() 
    { 

    while (ContinueRenderer()) 
    { 
    ALLEGRO_BITMAP *bitmap = al_clone_bitmap (nextBitmap); 
    DrawBitmapOnScreen (bitmap); 
    } 

    } 

这似乎不稳定.. 。可能会在al_clone_bitmap的电话中发生,但我不太确定如何处理这样的事情。我会在位图上使用互斥锁,但互斥锁似乎需要时间锁定和解锁,我希望这两个线程(特别是游戏引擎线程)尽可能快地运行。我也读了一些叫做条件的东西,但我完全不知道一个条件如何适用或有用,尽管我确定它们是。有人能指点我一个关于互斥体和条件的教程(最好是POSIX,而不是Windows),所以我可以试着弄明白这一切吗?

+0

一些Allegro说明:Allegro已经在特定平台所需的不同线程上运行各种组件。还要注意,给定显示的所有绘图操作都需要从创建显示的同一个线程发生。如果从辅助线程加载位图,则可以在显示线程上调用'al_clone_bitmap()',但不应该在每个帧上都这样做。国际海事组织,你不应该因为使用更多线程的理由而钓鱼。 – Matthew

回答

1

如果我在存储器中的数据的部分(比如,一个指向数据 结构),是它好一个线程写入它的意志和 另一个阅读从它随意

答案是“它取决于”,通常意味着“不”。

根据你写什么/读取,并且根据你的程序的逻辑,你可以与野生结果或腐败风,如果你尝试写,没有同步阅读,你不能绝对确保写入并且读取是原子的。

所以,你应该只使用一个互斥体,除非:

  1. 你绝对相信,写入和读取是原子,而你绝对相信,一个线程只能读取(理想情况下,你会使用一些对原子操作(如WinAPI中的Interlocked函数家族)的特定支持)。
  2. 你绝对需要从未锁定的微小性能增益。

另外值得一提的是您的while (using);结构将是一个很多更可靠,正确的,并且如果使用可能会甚至获得更好的效果spin lock(如果你又绝对相信你需要一个自旋锁,而不是互斥)。

0

'google'中有很多手册页。搜索他们。我在几个搜索分钟内找到了http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

此外,从一个这么小的例子开始,增加难度。具有线程创建和终止,线程返回,线程sincronization的Firstable。继续posix互斥和条件并理解所有这些条款。

一个重要的文档饲料是Linux手册和信息页。

好运

1

您需要的工具被称为原子操作这将确保读者线程只读取其他线程写入的整个数据。如果您不使用这些操作,则数据只能被部分读取,因此读取的内容可能对您的应用程序而言可能毫无意义。

新标准C11具有这些操作,但尚未广泛实施。但是许多编译器应该有扩展来实现这些。例如,gcc具有一系列内置函数,以__sync前缀开头。

0

如果非要在存储器中的数据的部分(比如说,一个指针指向一个数据结构),是它好用于一个线程写入它随意,另一个随意从中读取,或者将各线程必须使用互斥锁来锁定内存,然后读取或写入,然后解锁?

如果您在内存中有两个不同线程正在读取和写入的数据部分,这称为关键部分,并且是消费者和生产者的常见问题。

有迹象表明,这个问题讲了许多资源:

但是,是的,如果你要使用两个不同的线程读取和写你必须实现互斥或其他形式的锁定和解锁。