スレッド (thread)

サブスレッドの生成とスレッド間の同期。

C言語

メイン、サブ、2つのスレッドで、同時にそれぞれ "A", "a" を10個出力し、双方の出力が完了した後に改行を出力する。

#include <stdio.h>
#include <pthread.h>
#include <sched.h>


pthread_mutex_t mutex;
pthread_cond_t cond;

void *subThread(void *arg)
{
	int cnt;

	pthread_mutex_lock(&mutex);
	// メインスレッドへの開始合図
	pthread_cond_signal(&cond);
	pthread_mutex_unlock(&mutex);

	// 処理
	for (cnt = 0; cnt < 10; cnt++) {
		pthread_mutex_lock(&mutex);
		putchar('a');
		pthread_mutex_unlock(&mutex);

		// メインスレッドに実行の機会を与える
		sched_yield();
	}

	return NULL;
}

void mainThread(void)
{
	pthread_t th;
	int cnt;

	// mutex, cond 初期化
	pthread_mutex_init(&mutex, NULL);
	pthread_cond_init(&cond, NULL);

	// メインが wait する前にサブが signal しないように lock
	pthread_mutex_lock(&mutex);

	// サブスレッド作成〜開始
	if (pthread_create(&th, NULL, subThread, NULL) != 0) {
		return;
	}
	// サブスレッドの開始合図待ち
	pthread_cond_wait(&cond, &mutex);
	pthread_mutex_unlock(&mutex);

	// 処理
	for (cnt = 0; cnt < 10; cnt++) {
		pthread_mutex_lock(&mutex);
		putchar('A');
		pthread_mutex_unlock(&mutex);

		// サズスレッドに実行の機会を与える
		sched_yield();
	}

	// サズスレッド終了待ち
	pthread_join(th, NULL);

	putchar('\n');

	// mutex, cond 開放
	pthread_cond_destroy(&cond);
	pthread_mutex_destroy(&mutex);
}

メニューに戻る

Java

メイン、サブ、2つのスレッドで、同時にそれぞれ "A", "a" を10個出力し、双方の出力が完了した後に改行を出力する。

Thread th = new Thread() {
	public void run() {
		// メインスレッドへの開始合図
		synchronized (this) {
			notify();
		}

		// 処理
		for (int cnt = 0; cnt < 10; cnt++) {
			synchronized (this) {
				System.out.print("a");
			}

			// メインスレッドに実行の機会を与える
			try { sleep(1); } catch (InterruptedException e) { }
		}
	}
};

// メインが wait する前にサブが notify しないように synchronize
synchronized (th) {
	// サブスレッド開始
	th.start();

	// サブスレッドの開始合図待ち
	try { th.wait(); } catch (InterruptedException e) { }
}

// 処理
for (int cnt = 0; cnt < 10; cnt++) {
	synchronized (th) {
		System.out.print("A");
	}

	// サズスレッドに実行の機会を与える
	try { th.sleep(1); } catch (InterruptedException e) { }
}

// サブスレッド終了待ち
try{ th.join(); } catch (InterruptedException e) { }

System.out.println("");

sleep(1) は実際には yield() が良い。実験では yield() だと別スレッドに移らないケースが目立ったので、sleep にした。

メニューに戻る

Python

高水準のスレッドインターフェース threading は、Java と同様の機能を備えている。低水準の thread を使うのは、ちょっと大変かもしれないので、高水準な threading の例のみ。

メイン、サブ、2つのスレッドで、同時にそれぞれ "A", "a" を10個出力し、双方の出力が完了した後に改行を出力する。

import sys
import threading
import time

def sub(cond):
	# メインスレッドへの開始合図
	cond.acquire()
	cond.notify()
	cond.release()

	# 処理
	for cnt in xrange(0,10):
		cond.acquire()
		sys.stdout.write("a")
		cond.release()
		# メインスレッドに実行の機会を与える
		time.sleep(0)

cond = threading.Condition()

# メインが wait する前にサブが notify しないように synchronize
cond.acquire()
# サブスレッド開始
th = threading.Thread(target = sub, args = (cond,))
th.start()

# サブスレッドの開始合図待ち
cond.wait()
cond.release()

# 処理
for cnt in xrange(0,10):
	cond.acquire()
	sys.stdout.write("A")
	cond.release()

	# サブスレッドに実行の機会を与える
	time.sleep(0)

# サブスレッド終了待ち
th.join()

print

Python 2.4 では、上の例に示したように、

cond.acquire()
...
cond.release()

と書かなければならないが、Python 2.5 からは以下のようにより簡潔に書けるようになった。

with cond:
	...

メニューに戻る

Ruby

メイン、サブ、2つのスレッドで、同時にそれぞれ "A", "a" を10個出力し、双方の出力が完了した後に改行を出力する。

require "thread"

mutex = Mutex.new
cond = ConditionVariable.new
th = nil

# メインが wait する前にサブが signal しないように synchronize
mutex.synchronize {
	# サブスレッド開始
	th = Thread.start() {
		# メインスレッドへの開始合図
		mutex.synchronize {
			cond.signal
		}

		# 処理
		(0...10).each { |cnt|
			mutex.synchronize {
				print "a"
			}

			# メインスレッドに実行の機会を与える
			Thread.pass
		}
	}

	# サブスレッドの開始合図待ち
	cond.wait(mutex)
}

# 処理
(0...10).each { |cnt|
	mutex.synchronize {
		print "A"
	}

	# サブスレッドに実行の機会を与える
	Thread.pass
}

# サブスレッド終了待ち
th.join()

puts

メニューに戻る