マルチスレッドプログラミング相談室 その8at TECH
マルチスレッドプログラミング相談室 その8 - 暇つぶし2ch527:デフォルトの名無しさん
10/12/19 17:24:15
処理系によるんじゃないでしょうか

528:デフォルトの名無しさん
10/12/19 17:30:04
MT-Safe ってどういう意味?

529:デフォルトの名無しさん
10/12/19 17:30:49
複数のスレッドで安全という意味

530:デフォルトの名無しさん
10/12/19 17:32:51
>>527
POSIXというか、ぶっちゃけLinuxの標準ライブラリstdioでならどうでしょうか。
ここまで範囲限定したらスレチになんのかな?

531:デフォルトの名無しさん
10/12/19 17:35:10
POSIXのstdioで _unlocked が付いてないものはスレッドセーフです

532:デフォルトの名無しさん
10/12/19 19:46:28
つまりprintfはスレッドセーフってことか。ありがとう!

533:デフォルトの名無しさん
10/12/19 21:15:28
関数がってことで、使い方間違えると...

534:デフォルトの名無しさん
10/12/19 23:13:56
まぁ想像するだけでもprintfは外部に出力するからロックとか色々してるのは分かる
printfしたらバグが起こらなくなったとかで原因がスレッド絡みとかよくある

んでprintfで起こらなくなるから放置とかマジ勘弁してくださいorz

535:デフォルトの名無しさん
10/12/24 00:47:37
スレッドセーフなメモリの読み書きについて勉強しているのですが、情報が少なく捗りません。
メモリへの同時アクセスによるデータ破壊は、書き込み時にのみ起こると認識しているのですが、正しいでしょうか?

・二つのスレッドが一つの変数を書き換えるとき
 →データが破壊される場合がある。
 
・一つのスレッドが一つの変数を書き換え、別のスレッドがその変数を読み込むとき
 →書き込みは問題なく行われる。
 →読み込みは、書き換え途中のデータを読み込む場合がある。

・二つのスレッドが一つの変数を読み込むとき
 →問題なし。

536:デフォルトの名無しさん
10/12/24 01:06:26
書き込まないものを読み込むことにどんな意味があるのだろうか

537:デフォルトの名無しさん
10/12/24 01:10:53
const 定数ですね

538:デフォルトの名無しさん
10/12/24 01:43:18
>>535
いずれも正しい。

539:デフォルトの名無しさん
10/12/24 06:02:20
ありがとうございます。理解が深まりました。

540:デフォルトの名無しさん
10/12/24 09:17:21
>>535
> ・二つのスレッドが一つの変数を書き換えるとき
>  →データが破壊される場合がある。

データの破壊とは何ぞや?単に後から書いたデータが残る。それだけの話。

541:デフォルトの名無しさん
10/12/24 09:53:16
それぞれの書き込みがアトミックならね。

32ビットマシンで64ビットの書き込みとか、アトミックでない場合、破壊が起こるかもしれない。

542:デフォルトの名無しさん
10/12/24 15:07:31
>>540
配列だって、立派な配列変数だぜ。
文字列型変数もあるしな。

543:540
10/12/24 15:52:35
そうだった、最近のデータはでかいんだな。
組み込み系のスレ見た後だったから頭がアセンブラレベルになってた。
失礼。

俺はどっちにしてもミューテックスかクリティカルセクションで排他しておくけど。

544:デフォルトの名無しさん
10/12/24 17:17:54
同時アクセス時の挙動なんてCPUの仕様次第だろ
同時読込なら安全なんて確証は無い

545:デフォルトの名無しさん
10/12/24 17:20:04
データが小さければ読み書きのキャッシュ問題とか無視できるが、
今はふつうに扱う標準データが大きいからなあ。プログラミングも大変だ。

546:デフォルトの名無しさん
10/12/24 17:20:27
アホ発見

547:デフォルトの名無しさん
10/12/24 17:30:42
同時読込なら安全なんて確証は無い・・・
ということは同じ関数を同時に実行するとまずい場合があるってことか
同じ関数を同時に実行すると同じ命令列を同時に読込むことになるもんな

548:デフォルトの名無しさん
10/12/25 20:23:56
言語仕様じゃなくハードウェア仕様だと理解してればいい
大丈夫かどうかを言語仕様で調べても守備範囲外のことで規定されてないから無駄

549:デフォルトの名無しさん
10/12/25 20:28:39
いや失礼、言語仕様で規定されてる物もあるか

550:デフォルトの名無しさん
10/12/26 16:17:56
printfがスレッドセーフじゃないのはわかるけど
どうしてsprintfがスレッドセーフではないのはなぜ?

551:デフォルトの名無しさん
10/12/26 16:24:32
>>550
内部にスタテックバッファーを持ってるかも。

552:デフォルトの名無しさん
10/12/26 16:54:42
>>551
まじか・・・だらしのないやつだなsprintfも・・・

553:デフォルトの名無しさん
10/12/26 17:45:40
おまえが使ってるライブラリを実装したところに聞けよ

554:デフォルトの名無しさん
10/12/26 18:09:36
sprintfがスレッドアンセーフってのはどこ情報?

555:デフォルトの名無しさん
10/12/26 19:50:50
あとだしで申し訳ないがライブラリはglibcです

>>554
URLリンク(slashcolon.com)
URLリンク(www.kmonos.net)
Dでスレッドセーフにしました=Cだとスレッドセーフちがう
と解釈しました

ていうか、そもそもprintfがスレッドセーフだという情報がない。
不明なうちはアンセーフ扱いするのが俺のジャスティス

556:デフォルトの名無しさん
10/12/26 20:00:44
なるほど
確かに

557:デフォルトの名無しさん
10/12/26 20:13:26
それ英語版見たらスレッドセーフなんてどこにも書いてないぞ・・・
> writefln() improves on printf() by being type-aware and type-safe:
誤訳じゃないのか

558:デフォルトの名無しさん
10/12/26 20:16:54
URLリンク(stackoverflow.com)
適当にぐぐったけどglibcはスレッドセーフとか書いてるような感じ

559:デフォルトの名無しさん
10/12/27 11:09:50
へえ

560:デフォルトの名無しさん
10/12/27 14:34:33
探しても「セーフだろう」「たぶんセーフ」ばっかりしか出てこない
むずむずするなぁ

561:デフォルトの名無しさん
10/12/27 15:03:50
IEEE Std 1003.1-2001の定義では、例外的にアンセーフで良いとされているもの以外は
スレッドセーフ。

URLリンク(pubs.opengroup.org)

562:デフォルトの名無しさん
10/12/28 19:19:26
過去スレ全部はみれなかったんだけど、マルチスレッド関連の良書をまとめてみる。
この他にこれがいいとかあったり、これ駄目とかあったら教えて。


[一般]
並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング

The Art of Multiprocessor Programming 並行プログラミングの原理から実践まで

増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編


[java]
Javaスレッドプログラミング―並列オブジェクト指向プログラミングの設計原理 (OO SELECTION)

Concurrency: State Models and Java Programs 2edition

Java並行処理プログラミング ―その「基盤」と「最新API」を究める


[windows]
Win32 マルチスレッド プログラミング

Advanced Windows 第5版 上
Advanced Windows 第5版 下


[Unix]
POSIXスレッドプログラミング



563:デフォルトの名無しさん
10/12/31 19:52:51
[C++]
インテルスレッディング・ビルディング・ブロック

主にこのライブラリの使い方だが、
他にもスレッド管理の考え方が載ってる。まぁオープンソースなので見れるのだけど

564:デフォルトの名無しさん
11/01/03 21:56:27
ありがとうございます。C++の良書をあまり知らないので助かります。


565:デフォルトの名無しさん
11/01/15 09:14:58
concurrent hashmapのC++実装って
なんでないの?

566:デフォルトの名無しさん
11/01/15 09:49:16
>>565
キミのためにお取り置きしてある。

567:デフォルトの名無しさん
11/01/15 10:31:02
>>566
並列mapでいいから実装ないの?
C++って並列コンテナないから何もできないよね

568:デフォルトの名無しさん
11/01/15 18:21:33
>>567
キミが作るだろうと思って残しておいた。

569:デフォルトの名無しさん
11/01/16 11:14:37
>>567
俺のところにはある。

570:デフォルトの名無しさん
11/01/16 11:28:44
C/C++はアセンブラと高級言語の間みたいな位置だからな
言語そのものを作るとか、OSを作るとか、リソースの厳しい組み込み系で作るとか、
そういう用途じゃないなら別に強力な言語ではない
ネイティブのCPUの挙動を理解しないとC/C++の有用性は半減すると思われ

571:デフォルトの名無しさん
11/01/25 23:02:03
すみません、spin-lockをしている間にCPUの使用率を下げる方法を知っている方はいますか?
調べてみると、rep;nop命令やSSEのpause命令をがそれに該当するように思えるのですが、
使ってみても何ら変わりませんでした。
スピンロックつかっわないとは思うんだけど。
自作のスレッドバリア関数(自作のspin_lock)を作って、
たとえば、
if(threadnum=5) sleep(10);
my_barirrer();
とするとスレッド5を待っている間は5以外のCPU使用率が100%近くなってしまいます。
それに対してOpenMP使った場合では、
if(threadnum=5) sleep(10);
#paragma omp barirrer

だと待っている間はCPU使用率は殆ど変わりません。
ちなみに自作のspinlockは下記のような感じです。
if(thread_num == 0)
{
asm volatile(
"Loop1:\n\t\t"
"movl (%0), %%eax\n\t\t"
"movl (%1), %%ebx\n\t\t"
"lfence\n\t\t"
"cmpl %%ebx, %%eax\n\t\t"
"rep;nop\n\t\t"
"jne Loop1\n\t\t"
:
:"r"(&lock->sync), "r"(&lock->maxthreads)
:"memory","%eax","%ebx"
);

というか、これって間抜けですかね?

572:デフォルトの名無しさん
11/01/25 23:10:46
自前でタスク切換えみたいなことするしか

573:デフォルトの名無しさん
11/01/25 23:15:42
>>571
>>369

574:デフォルトの名無しさん
11/01/25 23:24:51
>>573
お前友達いないだろ

575:デフォルトの名無しさん
11/01/25 23:34:47
>>571
Sleepさせりゃいいんじゃね。

576:デフォルトの名無しさん
11/01/25 23:44:45
割り込みでしか切り替わらないコードで使用率下げたいというのが

577:デフォルトの名無しさん
11/01/28 22:22:30
さむいな(´・ω・`)

578:デフォルトの名無しさん
11/01/28 22:43:23
寒稲

579:デフォルトの名無しさん
11/01/31 22:10:29
>>571
CPU使用率が100%じゃないロックなんて、スピンロックとは認めない。

580:デフォルトの名無しさん
11/02/01 00:53:40
そもそも100%じゃないってことはコンテキストスイッチしてるってことになるでしょ?
何のためのスピンロックなのよあり得ない。


581:デフォルトの名無しさん
11/02/01 10:50:42
スリープロックのループもスピン扱いすることもあるから何とも

582:デフォルトの名無しさん
11/04/04 19:37:25.20
ちょっと聞いていい?

以下のコードでnotifyAllされたらどうなるのって質問

void A()
  synchronized(Lock){
    if(List.size() == 0){
      try{ Lock.wait(); }(Exception e){}
    }
    //以下処理続く
  }
}

このコードで複数のスレッドが待ち状態だったらnotifyAllとき再度Lockを取りに行ってくれるの?
もし、そうだったとしたら。
結局はnotifyで1つのスレッドのみ動かすってのと同じことになるの?

それとも再起処理的に以下のようにしなきゃだめ?
void A()
  synchronized(Lock){
    if(List.size() == 0){
      try{ Lock.wait(); }(Exception e){}
      A(); ←ここでさらに再帰的に同じメソッドを呼び出す
    }
    //以下処理続く
  }
}

おしえてエロイひと。。。

583:デフォルトの名無しさん
11/04/04 19:47:38.94
>>582
notifyAll を呼ぶと、wait してたスレッドはすべて起きて、 Lock を取りに行く
どうせみんなすぐには取れないから Lock 待ち状態になるが、すでに wait からは外れてるので、 Lock を取れた順にすべてのスレッドが動き出す

notify の場合は、wait してたスレッドのうちひとつだけが起きて Lock を取りに行く
他のスレッドは、その後 Lock が空いても、眠ったまま起きない

wait はふつう再帰じゃなくて while にする
synchronized (Lock) {
 while (List.size() == 0) {
  Lock.wait();
 }
}
waitは、notifyされてなくても間違って起きることがあるらしいので、このように書くべきこととされている

584:デフォルトの名無しさん
11/04/04 20:17:38.60
>notifyAll を呼ぶと、wait してたスレッドはすべて起きて、 Lock を取りに行く
ということはnotifyAllでそのまま下に処理が流れていくんじゃなくて

再度 synchronized(Lock){ ←この部分に処理が戻ってくるイメージなんですかね?

別のメソッド内の以下のようなコードでnotifyAllをかけようと思ってたんだけど、
ちゃんとnumの個数分以上のスレッドは再度、wait状態に入ってくれるのか心配でした
  for(int i = 0 ; i < num ; i++){
    List.add(object);
  }
  Lock.notifyAll();

それと。
 while (List.size() == 0) {
   Lock.wait();
 }
これしなきゃいけないんですね。Javadoc見てきました。

>>583 ありがとー。

585:デフォルトの名無しさん
11/04/04 21:55:04.24
>>584
synchronized のところまで戻るわけじゃなく、synchronized の中にいるまま、 wait のところで、
Lock をいったん解放、おやすみなサイして、起きたら元通りに取りにいく
wait は synchronized の中でありながら Lock を手放している特殊な場所

notifyAll を呼んだ側のスレッドは、notifyAll を呼んだあとそのまま下に流れていく
というのも、notifyAll を呼んだ時点では Lock は notifyAll 側のスレッドが握ってるので (synchronized 中のはず)、
wait 側のスレッドは起きるけれども、Lock を取れない
notifyAll 側が synchronized から抜けるなりして Lock を解放すると、wait 側が Lock を取って動き出せるようになる


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch