List方法呼叫執行緒同步問題

2021-06-13 16:48:02 字數 3671 閱讀 7922

這是在呼叫list的addrange方法時,遇到「system.argumentexception: 目標陣列的長度不夠。請檢查 destindex 和長度以及陣列的下限。」的問題。

初步估計是執行緒安全的問題。

覺得它對這個問題的分析相對獨特,故轉過來了。

system.argumentexception: 目標陣列的長度不夠。請檢查 destindex 和長度以及陣列的下限。

在 system.array.copy(array sourcearray, int32 sourceindex, array destinationarray, int32 destinationindex, int32 length, boolean reliable)

在 system.array.copy(array sourcearray, int32 sourceindex, array destinationarray, int32 destinationindex, int32 length)

在 system.collections.generic.list`1.toarray()

這是怎麼回事?

這裡說說怎麼避免這問題出現。

因為之前沒有大量的對list的測試,也不知道,list是否執行緒安全的。當然執行緒安全的,

總得要有同步操作。這裡肯定就會耗效能了。

list.toarray()出異常了? 我想:出於效能考慮,.net 的list.toarray()內的操作沒有加鎖同步處理。

如下**解說:

c# code

? 1

2

3

4

5

6

publict toarray()

以上**是用.net refelctor 反編譯的。list.toarray()方法內的**。

果然是沒有加lock或是其它的同步操作。

原因:有兩操作a,b,分別非同步的操作了乙個.add(t item)或是.remove(t item)方法別乙個list的.toarray()。

然後,在第乙個先操作的,指令在時間片上,佔第一位。

c# code

? 1

2

3

4

5

6

7

8

9

publicvoidadd(t item)

this._items[this._size++] = item;

this._version++;

}

從上面來看,add(t item)也是沒有加同步鎖的

if (this._size == this._items.length)//a的

假設:緊跟著下一條執行的指令應該是:

t destinationarray = new t[this._size];//b的

但,由於非同步操作。

然後,在第二個操作的時候,因為是非同步的,所以有可能在第乙個操作的指令

緊跟著要執行的指定就成了第二個操作的第乙個指令,依此類推下去,將所有執行順序的列出來

//假設:執行前,this.count == 10

if (this._size == this._items.length)//a的

this.ensurecapacity(this._size + 1);//a的

t destinationarray = new t[this._size];//b的 假設計this.count = 10

this._items[this._size++] = item;//a的,這時,this.count == 11了

array.copy(this._items, 0, destinationarray, 0, this._size);

//b的,這時,所有this.count == 1,而剛定義的destinationarray.length == 10的,

//所以這時,一旦執行copy就會出下限不足的異常。

所以,現在我們知道了list不是執行緒安全的,很多時候,我們都必須自己要對list的操作前,加個鎖,同步一下。

例如:正常**:

c# code

? 1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

classtestclass{}

staticlisttestclasslist =newlist();

staticvoidmain()

}

voidthreadmethod()

異常**:

c# code

? 1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

classtestclass{}

staticlisttestclasslist =newlist();

staticvoidmain()

}

voidthreadmethod()

}

多執行緒例項呼叫同步方法

針對執行緒同步,做了個小例子。1.多執行緒例項化多個物件,呼叫同步方法 2.多執行緒通過單例,呼叫同步方法 public class mytest 單例物件不被建立 public static mytest mytest null 方便測試,就不寫 public static void main s...

C 將List資料分執行緒同步呼叫

最近公司專案需要,要進行多執行緒進行耗時,特意寫了個多用途泛型類,以供後續使用 public class autorunthread public void starttask k action allcompletetask null where k runthreadbase new ttt.p...

執行緒同步問題

昨天簡單研究了一點執行緒的同步問題 package com.pb.thread public class waymakethread 建立乙個執行緒,繼承thread類 class mythread extends thread 建立乙個類,實現runable介面,這不是乙個執行緒類 class m...