У меня есть одно сомнение. Известно, что StringBuffer
является потокобезопасным (его методы synchronized
), в отличие от StringBuilder
который не является потокобезопасным.
Если StringBuffer
, он сам является потокобезопасным, то зачем мне его вставлять в synchronized block
при его изменении. Ниже приведен код:
class SyncTest extends Thread
{
StringBuffer sb;
public SyncTest(StringBuffer sb)
{
this.sb = sb;
}
public void run()
{
synchronized(sb)
{
for(int i = 1;i<=10;++i)
{
System.out.print(sb);
}
sb.setCharAt(0, (char) (sb.charAt(0)+1));// incrementing the char by 1, thus modifying the StringBuffer
}
}
public static void main(String [] args)
{
StringBuffer sb = new StringBuffer("A");
new SyncTest(sb).start();
new SyncTest(sb).start();
new SyncTest(sb).start();
}
}
Вывод:
AAAAAAAAAA
BBBBBBBBBB
CCCCCCCCCC
Когда я удаляю synchronized block
изменения выходного synchronized block
и изменяется, как показано ниже:
AAAAAAAAAAAAAAAAA
ABBBBBBBB
ACCC
Итак, что это значит, когда мы говорим, что StringBuffer
является потокобезопасным. Может ли кто-нибудь убрать мои сомнения по этому поводу?
Вы выполняете сложную операцию. Вы оба показываете это и изменяете его. Само по себе обе операции являются потокобезопасными, но в сочетании с этим они не являются.
Один поток может изменять содержимое, в то время как другой поток отображает отдельные символы.
Синхронизируемый StringBuffer
означает, что каждый вызов метода синхронизирован, но два последовательных вызова не являются.
Если вы это сделаете
sb.append("Hello Dolly");
Вам гарантировано, что никакая другая операция не добавит ничего в середине двух слов.
Если вы это сделаете
sb.append("Hello ");
sb.append("Dolly");
В sb
может содержаться Hello whateverDolly
.
Единственный способ избежать первого - выполнить синхронизацию в том контексте, где это необходимо.
StringBuffer
являются потокобезопасными; две операции, одна за другой, нет. Обратите внимание, что то же самое относится и кHashtable
.