<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>路上 &#187; 编程</title>
	<atom:link href="http://www.speedvi.net/tag/%e7%bc%96%e7%a8%8b/feed" rel="self" type="application/rss+xml" />
	<link>http://www.speedvi.net</link>
	<description>为者常成 行者常至</description>
	<lastBuildDate>Sat, 12 Jun 2010 06:30:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>多线程中壁垒(barrier)的使用</title>
		<link>http://www.speedvi.net/2010/01/27/195.html</link>
		<comments>http://www.speedvi.net/2010/01/27/195.html#comments</comments>
		<pubDate>Wed, 27 Jan 2010 07:41:06 +0000</pubDate>
		<dc:creator>行者</dc:creator>
				<category><![CDATA[操作系统]]></category>
		<category><![CDATA[壁垒]]></category>
		<category><![CDATA[线程]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.speedvi.net/2010/01/27/195.html</guid>
		<description><![CDATA[　　前面我们讲过main()函数与工作线程结束进行的同步，在那里提到了两种方式：pthread_join()函数以及壁垒(barrier)。 　　现在我们回到房子的比喻，假设这个家庭准备到哪个地方旅行。司机上了小货车并发动了引擎。之后，司机就开始等待。只有全部的家庭成员都上车之后，这个小货车才会开动——因为我们不想把任何人落下！ 　　这和我们在前面说的那个绘图程序的原理是一模一样的。主线程要等待全部工作线程结束后，才执行下一步的程序。 　　不过和这个比喻还有一个很大的差别。那就是通过使用pthread_join()函数，我们是等待所有工作线程的结束。也就是说，之后这些线程已经不存在了，它们退出了。 　　通过使用壁垒(barrier)，我们可以等待某些数量的线程在壁垒处集合。在设定的数目达到之后，我们解锁这些线程，让它们继续运行。 　　你先要使用pthread_barrier+init()函数来创建壁垒： #include &#60;pthread.h&#62; int pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count); 　　这段程序在传送的地址处（指向壁垒对象的指针barrier）创建一个壁垒对象，这个壁垒对象的属性通过attr进行设置，我们也可以使用NULL来使用默认设置。必须调用pthread_barrier_wait()函数的线程的个数通过count设定。 　　一旦壁垒创建成功之后，我们就可以让线程在其结束之后调用pthread_barrier_wait()函数来声明其已经结束。代码如下： #include &#60;pthread.h&#62; int pthread_barrier_wait (pthread_barrier_t *barrier); 　　当一个线程调用pthread_barrier_wait()函数，它就会进入阻塞状态，直到在pthread_barrier_init()函数中设定的那么多数量的线程调用pthread_barrier_wait()函数为止。当正确数量的线程调用了那个函数，所有的这些线程就会被“同时”解除阻塞。 　　例子如下： /* * barrier1.c */ #include &#60;stdio.h&#62; #include &#60;time.h&#62; #include &#60;pthread.h&#62; #include &#60;sys/neutrino.h&#62; pthread_barrier_t barrier; // the barrier synchronization object void * thread1 (void *not_used) { time_t now; [...]


Related posts:<ol><li><a href='http://www.speedvi.net/2010/02/24/211.html' rel='bookmark' title='用于线程同步的条件变量(Condition Variables)'>用于线程同步的条件变量(Condition Variables)</a> <small>　　条件变量(condition variables或condvars)与前面讲的睡眠锁(sleepon lock)非常类似。而实际上睡眠锁是在条件变量的基础上构建的，这也是为什么我们在睡眠锁的例子的解释表中有一个CONDVAR状态。它也能通过不停的调用pthread_cond_wait()函数来释放互斥体、等待以及重新获取互斥体，和pthread_sleepon_wait()函数一样。 　　下面我们就略过初始化的步骤，并使用条件变量来重新完成sleepon部分的那个生产者与消费者的多线程的程序。之后再讨论调用的函数。 &nbsp; /* * cp1.c */ #include...</small></li>
<li><a href='http://www.speedvi.net/2010/01/18/191.html' rel='bookmark' title='线程的启动'>线程的启动</a> <small>　　任何线程在同一个进程中都可以创建另一个线程，这没有任何的限制。创建线程最常用的就是POSIX函数pthread_create()，该函数的定义如下： #include &lt;pthread.h&gt; int pthread_create (pthread_t *thread, const pthread_attr_t *attr,...</small></li>
<li><a href='http://www.speedvi.net/2010/02/26/213.html' rel='bookmark' title='线程池(Pools of threads)'>线程池(Pools of threads)</a> <small>　　在编程中你可能注意到你想要能够运行多个线程，并且你也想在某个限度上控制这些线程的行为。例如，在一个服务器中，你可能决定只让一个线程阻塞，等待来自客户端的一个消息。当这个线程获得了消息并开始处理这个请求的时候，你可能需要再创建一个新的线程来等待下一个请求的到来，以便在新的请求到了的时候由这个线程完成相应的处理。如此下来，过了一段时间所有的请求都被处理之后，你就会有多个线程在那里等待后续的客户端请求了。为了保护资源，你可能需要杀掉一些多余的线程。 　　这其实是一个常见的操作，Neutrino实时系统也提供了一个库来帮助处理这些操作。 　　现在需要注意的是这些线程池中的线程做了两个不同的操作： &nbsp; 阻塞（等待操作）　　 处理操作 　　阻塞操作并不消耗CPU。在典型的服务器中，线程就是这样等待消息的到达的。这与处理操作是不同的，处理操作根据处理结构的不同有可能消耗或不消耗CPU。 　　系统提供了如下的函数来处理线程池： #include &lt;sys/dispatch.h&gt;...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>　　前面我们讲过main()函数与工作线程结束进行的同步，在那里提到了两种方式：pthread_join()函数以及壁垒(barrier)。</p>
<p>　　现在我们回到房子的比喻，假设这个家庭准备到哪个地方旅行。司机上了小货车并发动了引擎。之后，司机就开始等待。只有全部的家庭成员都上车之后，这个小货车才会开动——因为我们不想把任何人落下！</p>
<p>　　这和我们在前面说的那个绘图程序的原理是一模一样的。主线程要等待全部工作线程结束后，才执行下一步的程序。</p>
<p>　　不过和这个比喻还有一个很大的差别。那就是通过使用pthread_join()函数，我们是等待所有工作线程的结束。也就是说，之后这些线程已经不存在了，它们退出了。</p>
<p><span id="more-195"></span>
<p>　　通过使用壁垒(barrier)，我们可以等待某些数量的线程在壁垒处集合。在设定的数目达到之后，我们解锁这些线程，让它们继续运行。</p>
<p>　　你先要使用pthread_barrier+init()函数来创建壁垒：</p>
<pre class="codesamp">#include &lt;pthread.h&gt;

int
pthread_barrier_init (pthread_barrier_t *<i class="var">barrier</i>,
                      const pthread_barrierattr_t *<i class="var">attr</i>,
                      unsigned int <i class="var">count</i>);</pre>
<p>　　这段程序在传送的地址处（指向壁垒对象的指针barrier）创建一个壁垒对象，这个壁垒对象的属性通过attr进行设置，我们也可以使用NULL来使用默认设置。必须调用pthread_barrier_wait()函数的线程的个数通过count设定。</p>
<p>　　一旦壁垒创建成功之后，我们就可以让线程在其结束之后调用pthread_barrier_wait()函数来声明其已经结束。代码如下：</p>
<pre>#include &lt;pthread.h&gt;

int
pthread_barrier_wait (pthread_barrier_t *<i>barrier</i>);</pre>
<p>　　当一个线程调用pthread_barrier_wait()函数，它就会进入阻塞状态，直到在pthread_barrier_init()函数中设定的那么多数量的线程调用pthread_barrier_wait()函数为止。当正确数量的线程调用了那个函数，所有的这些线程就会被“同时”解除阻塞。</p>
<p>　　例子如下：</p>
<pre class="codesamp">/*
 *  barrier1.c
*/

#include &lt;stdio.h&gt;
#include &lt;time.h&gt;
#include &lt;pthread.h&gt;
#include &lt;sys/neutrino.h&gt;

pthread_barrier_t   barrier; // the barrier synchronization object

void *
thread1 (void *not_used)
{
    time_t  now;
    char    buf [27];

    time (&amp;now);
    printf ("thread1 starting at %s", ctime_r (&amp;now, buf));

    // do the computation
    // let's just do a sleep here...
    sleep (20);
    pthread_barrier_wait (&amp;barrier);
    // after this point, all three threads have completed.
    time (&amp;now);
    printf ("barrier in thread1() done at %s", ctime_r (&amp;now, buf));
}

void *
thread2 (void *not_used)
{
    time_t  now;
    char    buf [27];

    time (&amp;now);
    printf ("thread2 starting at %s", ctime_r (&amp;now, buf));

    // do the computation
    // let's just do a sleep here...
    sleep (40);
    pthread_barrier_wait (&amp;barrier);
    // after this point, all three threads have completed.
    time (&amp;now);
    printf ("barrier in thread2() done at %s", ctime_r (&amp;now, buf));
}

main () // ignore arguments
{
    time_t  now;
    char    buf [27];

    // create a barrier object with a count of 3
    pthread_barrier_init (&amp;barrier, NULL, 3);

    // start up two threads, thread1 and thread2
    pthread_create (NULL, NULL, thread1, NULL);
    pthread_create (NULL, NULL, thread2, NULL);

    // at this point, thread1 and thread2 are running

    // now wait for completion
    time (&amp;now);
    printf ("main () waiting for barrier at %s", ctime_r (&amp;now, buf));
    pthread_barrier_wait (&amp;barrier);

    // after this point, all three threads have completed.
    time (&amp;now);
    printf ("barrier in main () done at %s", ctime_r (&amp;now, buf));
}</pre>
<p>　　主线程创建了壁垒并对其初始化，设定需要通过壁垒同步的线程的个数（也包括了它自己）。在我们的例子里面，个数为3——一个是main()线程，一个是thread1()，一个是thread2()。之后图像计算线程（thread1()与thread2()）开始运行。为了演示，我们没有列出图形计算的源代码，而是使用了sleep(20)和sleep(40)两个函数，来完成延迟，就像运算正在进行似的。为了同步，主线程在壁垒处阻塞了自己，在两个工作线程也在壁垒处集合之后，才会对其解除阻塞。</p>
<p>　　如前面所讲的，工作线程通过pthread_join()函数，只有这些工作线程结束并消亡之后主线程才能与它们同步。不过通过壁垒，这些线程可以继续存活。在实际中，它们是在全部结束之后从pthread_barrier_wait()函数处解除阻塞。这里的主意是让你准备好让这些线程做些事。在我们的图像的例子里面，它们没什么事情可做，因为我们就是这样写的代码的。在实际的应用中，你可能会让它们开始下一帧的计算了。</p>


<p>Related posts:<ol><li><a href='http://www.speedvi.net/2010/02/24/211.html' rel='bookmark' title='用于线程同步的条件变量(Condition Variables)'>用于线程同步的条件变量(Condition Variables)</a> <small>　　条件变量(condition variables或condvars)与前面讲的睡眠锁(sleepon lock)非常类似。而实际上睡眠锁是在条件变量的基础上构建的，这也是为什么我们在睡眠锁的例子的解释表中有一个CONDVAR状态。它也能通过不停的调用pthread_cond_wait()函数来释放互斥体、等待以及重新获取互斥体，和pthread_sleepon_wait()函数一样。 　　下面我们就略过初始化的步骤，并使用条件变量来重新完成sleepon部分的那个生产者与消费者的多线程的程序。之后再讨论调用的函数。 &nbsp; /* * cp1.c */ #include...</small></li>
<li><a href='http://www.speedvi.net/2010/01/18/191.html' rel='bookmark' title='线程的启动'>线程的启动</a> <small>　　任何线程在同一个进程中都可以创建另一个线程，这没有任何的限制。创建线程最常用的就是POSIX函数pthread_create()，该函数的定义如下： #include &lt;pthread.h&gt; int pthread_create (pthread_t *thread, const pthread_attr_t *attr,...</small></li>
<li><a href='http://www.speedvi.net/2010/02/26/213.html' rel='bookmark' title='线程池(Pools of threads)'>线程池(Pools of threads)</a> <small>　　在编程中你可能注意到你想要能够运行多个线程，并且你也想在某个限度上控制这些线程的行为。例如，在一个服务器中，你可能决定只让一个线程阻塞，等待来自客户端的一个消息。当这个线程获得了消息并开始处理这个请求的时候，你可能需要再创建一个新的线程来等待下一个请求的到来，以便在新的请求到了的时候由这个线程完成相应的处理。如此下来，过了一段时间所有的请求都被处理之后，你就会有多个线程在那里等待后续的客户端请求了。为了保护资源，你可能需要杀掉一些多余的线程。 　　这其实是一个常见的操作，Neutrino实时系统也提供了一个库来帮助处理这些操作。 　　现在需要注意的是这些线程池中的线程做了两个不同的操作： &nbsp; 阻塞（等待操作）　　 处理操作 　　阻塞操作并不消耗CPU。在典型的服务器中，线程就是这样等待消息的到达的。这与处理操作是不同的，处理操作根据处理结构的不同有可能消耗或不消耗CPU。 　　系统提供了如下的函数来处理线程池： #include &lt;sys/dispatch.h&gt;...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.speedvi.net/2010/01/27/195.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

