Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52875
  • 博文数量: 18
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-24 10:18
文章分类

全部博文(18)

文章存档

2011年(1)

2010年(14)

2009年(3)

我的朋友
最近访客

分类:

2010-06-02 14:40:30

下面这些是ClanLib的线程类:
CL_Thread, CL_Runnable
CL_Mutex, CL_MutexSection
CL_ThreadLocalStorage

线程类
CL_Thread 是线程的句柄类。它将函数加入线程或者等待线程。使用CL_Thread::Start开妈线程。开始线程以多种方式存在,它使你在你的程序中更方便的按你指定的方式执行线程主函数。
class MyRunnable : public CL_Runnable
{
public:
    void run()
    {
        CL_Console::write_line("Hello from another thread");
    }
};

MyRunnable runnable;
CL_Thread thread;
thread.start(&runnable);
thread.join();

虽然以上的方法简单易懂,但它也强制要求你在每次开始一个线程时必须继承自一个类。另一些CL_Thread::start函数允许你直接指定一个函数做为参数。
void my_thread_main()
{
    CL_Console::write_line("Hello from another thread");
}

CL_Thread thread;
thread.start(&my_thread_main);
thread.join();

这个函数并不限制你必须使用静态方法,它很像CLanLib模板的回调类。你可以指定一个成员函数或者多个用户定义数据作为参数传递。
class MyClass
{
public:
    void thread_main(int param1, CL_String param2)
    {
        CL_Console::write_line("Hello from another thread");
    }
};

MyClass my_class;
CL_Thread thread;
thread.start(&my_class, &MyClass::thread_main, 42, "Hello");
thread.join();

使用 CL_Thread::join等待线程执行完后再关闭。如果不使用该方法,线程会直接关闭句柄。这意味着你的线程函数会继续运行,但你已失去了对它控制的权限。

Syncronization

除非另有规定,否则ClanLib的类是可重入的。这意味着要想线程安全,一个实例一次只能被一个线程使用。ClanLib使用了 CL_Mutex类来确保只有一个线程能操作数据或者共存函数。每个互斥类一次只能被一个线程锁定,如果同时有其它线程想要锁定互斥类,它将等待直到第一个锁定线程解锁。

class MyClass
{
public:
    CL_Mutex mutex;
    CL_String variable;

    void thread_main1()
    {
        for (int i = 0; i < 10000; i++)
        {
            mutex.lock();
            variable = "Modified from thread 1";
            mutex.unlock();
        }
    }
    
    void thread_main2()
    {
        for (int i = 0; i < 10000; i++)
        {
            mutex.lock();
            variable = "Modified from thread 2";
            mutex.unlock();
        }
    }
};

MyClass my_class;
CL_Thread thread1, thread2;
thread1.start(&my_class, &MyClass::thread_main1);
thread2.start(&my_class, &MyClass::thread_main1);
thread1.join();
thread2.join();

请注意互斥类一定要被释放,否则所有使用互斥类保护数据的线程将会进入死锁。在线程函数中抛出异常并不会解锁。可以通过使用try/catch语块或者 CL_MutexSection代替互斥类。

CL_MutexSection 为了确保所有的函数能被解锁,它在构造函数中加锁锁,在析构函数中解锁
void thread_main1()
{
    for (int i = 0; i < 10000; i++)
    {
        CL_MutexSection mutex_lock(&mutex);
        variable = "Modified from thread 1";
    }
}


线程本地存储(Thread local storage),简称TLS,在多线程中自动的为每个线程的线程特定数据进行分配存储。可以通过使用编译器的关键字来实现,例如在vc++中使用__declspec(thread) int tls_i = 1;同时这也意味着TLS不能用来存储类变量。

CL_ThreadLocalStorage 提供了在TLS中存储由 CL_SharedPtr管理的对象的方法。CL_ThreadLocalStorage::get_variable会为每个线程返回不同的变量。
一个简单的例子:
class MyClass
{
public:
    CL_String str;
    int i;
};

void thread_main()
{
    // Retrieve TLS variable:
    CL_SharedPtr tls_var(
        CL_ThreadLocalStorage::get_variable("my_var"));
       
    if (tls_var.is_null())
    {
        // First time this thread tries to get this object.
        // Create object and store it.
        tls_var = CL_SharedPtr(new MyClass);
        CL_ThreadLocalStorage::set_variable("my_var", tls_var);
    }
   
    tls_var->str = "Hello";
    tls_var->i = 42;
}

CL_Thread thread1, thread2;
thread1.start(&thread_main);
thread2.start(&thread_main);
thread1.join();
thread2.join();

如果已通过CL_Thread建了线程,那么在使用TLS函数前必须得先新建 CL_ThreadLocalStorage实例。CL_ThreadLocalStorage 对象销毁后TLS变量也会销毁。CL_Thread实例会在线程函数结束后自动销毁。
阅读(474) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~