クラス変数が怖いの図

2022-05-18

ruby

クラス変数とかクラスインスタンス変数がニガテ

必要性をあまり感じたことがないし、なんだかややこしい。
うかつに使うとこういうことになる。という図を書いて置いとく。

なにが怖いんだっけ?とか考えなくてすむように

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Foo
  @@foo = 999

  def self.xxx(num)
    @@foo = num
    puts "#{num}:#{@@foo}"
    puts "#{num}:#{@@foo}"
  end
end

threads = []

10.times do |i|
  threads << Thread.new do
    Foo.xxx(i)
  end
end
threads.each(&:join) 

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1:1
2:2
3:3
1:3
5:5
4:4
6:6
6:6
7:7
8:8
9:9
9:9
0:9
3:9
2:9
5:9
4:9
7:9
8:9

ステップに割り込まれて他のスレッドに書き換えられちゃってますね。
こわ。注意しましょう。

こんなクソ例だとシングルトンでも一緒ですね。
適切な例が思いつかない。定数とインスタンス変数で十分な人生だったということか。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Bar
  include Singleton

  def set_bar(num)
    @bar = num
  end

  def bar
    @bar
  end
end

class Baz
  def self.xxx(num)
    Bar.instance.set_bar(num)
    puts "#{num}:#{Bar.instance.bar}"
    puts "#{num}:#{Bar.instance.bar}"
  end
end

threads = []

10.times do |i|
  threads << Thread.new do
    Baz.xxx(i)
  end
end
threads.each(&:join) 
0:0
3:3
3:3
0:3
2:2
4:4
4:4
5:5
7:7
6:6
8:8
9:9
1:8
2:8
5:8
6:8
7:8
9:8
8:8

ちなみに排他制御したいときは Thread::Mutex を使うと良いようだ
このバカ例ならループで十分だけど。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Foo
  @@foo = 999

  def self.xxx(num)
    @@foo = num
    puts "#{num}:#{@@foo}"
    puts "#{num}:#{@@foo}"
  end
end

threads = []

100.times do |i|
  threads << Thread::Mutex.new.synchronize do
    Foo.xxx(i)
  end
end

0:0
0:0
1:1
1:1
2:2
2:2
3:3
3:3
4:4
4:4
5:5
5:5
6:6
6:6
7:7
7:7
8:8
8:8
9:9
9:9

コメント

投稿する

投稿したコメントはご自身で削除できません

不適切なコメントと判断した場合は管理側で削除することがあります