<>学習ノートの鍵とは何か

1955 ワード

以前はコンカレントについてあまり知られていませんでしたが、プログラムに競争条件があれば、Synchronizedを1つ追加すれば解決できると思います.多くのソースコードを発見した後、他の人がロックをかけるのは簡単ではないことに気づいた.方法にsynchroizedを加えるのは簡単ではない.

public List<String> lists = Collections
			.synchronizedList(new ArrayList<String>());

	public synchronized boolean listIfAbsent(String str) {
		boolean ifAbsent = lists.contains(str);
		if (!ifAbsent) {
			lists.add(str);
		}
		return ifAbsent;
	}

	public boolean listIfAbsent1(String str) {
		synchronized (lists) {
			boolean ifAbsent = lists.contains(str);
			if (!ifAbsent) {
				lists.add(str);
			}
			return ifAbsent;
		}

	}
       public static void main(String[] args) {
		final Test t = new Test();
		new Thread() {
			public void run() {

				if (!t.lists.contains("a")) {
					t.lists.add("a");
				}
				if (!t.lists.contains("b")) {
					t.lists.add("b");
				}
				// t.lists.set(0, "chenliang");
				System.out.println(t.lists);
			}
		}.start();

		t.listIfAbsent1("a");
		// t.listIfAbsent("b");

	}


この中にはlistIfAbsentとlistIfAbsentの2つの方法があります.1つは悲観的なロックと言えるはずです.もう1つはlistにロックをかけるだけです.thisにロックをかけるだけで、そのオブジェクトのすべてのデータドメインが保護されるべきだと思っていました.データドメインがすべてexposeされていても、テストを経て、私が間違っていることに気づきました.同じTestオブジェクトでも、スレッドAがlistIfAbsentを呼び出すと、スレッドBが実行します.
t.lists.add(「a」)では、この時何が起こりますか?私の前の理解では、スレッドBはスレッドlistのデータドメインを変更することはできません.しかし、実際には、結果はそうではなく、データが破壊され、スレッドに期限切れのデータが表示されます.
これは私が鍵というものを全然理解していないことを示しています.
実際、ロックはオブジェクトの属性であり、Objectオブジェクトには対応するロック属性があります.Testというオブジェクトにロックをかけましたが、他のスレッドがpublic listsプロパティを変更しているかどうかを確認することはありません.
私の理解では、鍵をかける場所は方法だけですが、このTest自体は鍵を代表していません.他のスレッドは、このLISTのように、tを介して他の共有メンバー変数にアクセスすることができる.複数のスレッドがこのロック方法を呼び出す場合、反発が発生します.