2011-09-08 33 views
8

Tôi đã có một mảng 2x2 mà tôi đã có hai chủ đề hoạt động trên.Java: làm thế nào để đồng bộ hóa truy cập mảng và những hạn chế về những gì đi trong một điều kiện đồng bộ

có thể sử dụng câu lệnh được đồng bộ hóa trong java trên một mảng không?

cách khóa hoạt động? thread java hướng dẫn nói rằng các tuyên bố đồng bộ hoạt động trên các đối tượng, vì vậy tôi đã không chắc chắn những gì họ có nghĩa là. Một trang web khác nói rằng tôi có thể đưa ra tuyên bố như

synchronized (array1[]){ 

} 

Điều này có đồng bộ hóa quyền truy cập vào mọi thứ trong mảng để mảng bị khóa với các chủ đề khác không?

nếu tôi có một hai d Mảng tôi có thể sử dụng

synchronized (array1[i]) để khóa một trong những dòng của mảng?

và là nó có thể để khóa mảng cá nhân đánh giá cao với một cái gì đó giống như

synchronized (array1[i][j]){ 

} 

Nhưng yeah, thủ thuật hoặc giúp đỡ được đánh giá cao rất nhiều. Trên thực tế tôi đã biến nó thành, đúng hay không. Nhưng tôi muốn biết để sử dụng trong tương lai

Trả lời

11

Có, bạn có thể đồng bộ hóa bằng cách sử dụng mảng làm đối tượng màn hình, vì mảng (thậm chí mảng nguyên thủy) là các đối tượng trong Java.

Bạn có thể đồng bộ hóa một khối mã trên một màn hình cụ thể như thế này:

public void myMethod() { 

    unsynchronized_statements... 

    synchronized(myMonitorObject) { 
     synchronized_statments... 
    } 

Đó là thực hành tốt nhất để đồng bộ hóa như vài dòng mã càng tốt.

Đồng bộ mã trên màn hình không ảnh hưởng đến màn hình theo bất kỳ cách nào, nó chỉ ảnh hưởng đến các chuỗi truy cập khối mã được đồng bộ. Trước khi thực hiện chuỗi có thể nhập vào khối mã, nó phải có 'khóa' trên màn hình. Thời gian chạy Java đảm bảo rằng nhiều nhất một luồng tại một thời điểm có thể có 'khóa' trên màn hình. Vì vậy, việc đồng bộ hóa trên mảng của bạn không cấm các khối mã không đồng bộ để truy cập nó! Bí quyết là đảm bảo rằng tất cả các thao tác bạn không muốn xảy ra đồng thời nằm trong các khối được đồng bộ hóa trên cùng một màn hình.

Vì Java không cung cấp mảng đa chiều, chỉ mảng mảng, bạn chắc chắn có thể đồng bộ hóa trên một mảng lồng nhau để đồng bộ hóa chi tiết hơn. Nếu bạn mô hình hóa mảng 2d dưới dạng một mảng các hàng, bạn chỉ có thể đồng bộ hóa trên các hàng, chứ không phải trên các cột vì trong các cột ví dụ đó không được biểu diễn dưới dạng mảng riêng biệt.

Bạn chỉ có thể đồng bộ hóa trên các giá trị mảng đơn nếu chúng không phải là primitve, do đó, Integer() thay vì int. Lưu ý rằng Integer() là một đối tượng bất biến, vì vậy bạn sẽ không thể thay đổi giá trị của nó. Một giải pháp sẽ là tạo đối tượng wrapper Cell() của riêng bạn với một getter và setter cho giá trị số chứa. Điều này sẽ cho phép bạn để cho một sợi có được một khóa trên các tế bào và thay đổi một cách an toàn giá trị của nó.

Bởi vì đó là ngày nghỉ của tôi, tôi quyết định có một số niềm vui và tạo ra một ví dụ làm việc về những gì bạn mô tả. Vâng, đây là ý tưởng của tôi về việc vui chơi.

Lớp học:

  • Matrix: đại diện của một ma trận 2ngày của các tế bào
  • Cell: wrapper cho một giá trị của ô ma trận
  • Operation: Một hoạt động trừu tượng về một loạt các tế bào
  • IncrementOperation: một Hoạt động gia tăng mỗi Giá trị ô
  • ReverseOperation: hoạt động đảo ngược orde r của các tế bào
  • Main: ứng dụng

Ứng dụng này bắt đầu nhiều hoạt động trên cùng một ma trận. Khối mã được đồng bộ hóa duy nhất là trong lớp Hoạt động. Nếu bạn loại bỏ đồng bộ hóa, kết quả sẽ sai vì hai thao tác đang thao tác cùng một hàng cùng một lúc.

Output khi đồng bộ:

[105, 104, 103, 102, 101] 
[110, 109, 108, 107, 106] 
[115, 114, 113, 112, 111] 
[120, 119, 118, 117, 116] 
[125, 124, 123, 122, 121] 
[130, 129, 128, 127, 126] 
[135, 134, 133, 132, 131] 
[140, 139, 138, 137, 136] 
[145, 144, 143, 142, 141] 
[150, 149, 148, 147, 146] 

Ví dụ đầu ra khi không đồng bộ:

[105, 4, 103, 102, 101] 
[110, 9, 108, 207, 106] 
[115, 14, 113, 212, 111] 
[120, 19, 118, 217, 116] 
[125, 124, 123, 122, 121] 
[130, 129, 128, 127, 126] 
[135, 34, 133, 232, 131] 
[140, 139, 138, 137, 136] 
[145, 144, 143, 142, 141] 
[150, 149, 148, 147, 146] 

Lưu ý rằng tôi đã thêm một số Thread.sleep() báo cáo trong việc triển khai hoạt động để tạo sự khác biệt giữa đồng bộ và thực hiện không đồng bộ rõ ràng hơn.

+0

Bạn không thể đồng bộ hóa trên nguyên thủy. Một khối đồng bộ yêu cầu một đối tượng để nó có thể sử dụng khóa liên quan của nó. –

+0

Tôi đã nói ở đâu bạn có thể đồng bộ hóa trên nguyên thủy? –

+0

Xin chào! Tôi không muốn âm thanh có nghĩa là, chỉ cần nhìn thấy dòng đầu tiên của bạn "Có, bạn có thể đồng bộ hóa bằng cách sử dụng một mảng như đối tượng màn hình, bởi vì mảng (thậm chí nguyên thủy) là đối tượng trong Java." Bạn nói rằng bạn có thể đồng bộ trên mảng vì chúng là đối tượng. Đúng rồi. Nhưng cũng nói thêm rằng các sự kiện nguyên thủy bị đe dọa là các đối tượng, nhưng chúng không phải. Trân trọng, Tiberiu. –

3

Không, việc đồng bộ hóa theo cách này chỉ có nghĩa là bạn đang khóa đối tượng mảng, không phải là bạn đang thực sự đồng bộ hóa quyền truy cập vào các phương thức của nó. Nếu mảng của bạn hiển thị với người khác, họ vẫn có thể truy cập/sửa đổi nội dung của nó bất kể nó có bị khóa hay không. Chỉ có họ không thể khóa trên nó cùng một lúc - nếu họ cố gắng (từ một chủ đề khác), họ sẽ bị chặn cho đến khi khóa được phát hành bởi người thâu tóm ban đầu của nó.

Nếu bạn muốn đảm bảo rằng chỉ có một chuỗi truy cập mảng của bạn (hoặc một phần tử của nó) tại một thời điểm, bạn cần đóng gói nó trong một lớp và đồng bộ hóa tất cả các phương thức lớp công khai thao tác mảng. (Tuy nhiên, bạn có thể khóa mảng cho mục đích này, nếu bạn muốn - cách tiếp cận đơn giản và thông thường hơn là tự khai báo các phương thức là synchronized, trong trường hợp nội dung của chúng được đồng bộ hóa trên this, đối tượng kèm theo).

class ArrayWrapper { 
    private int[] array = ...; 

    public void setValue(int index, int value) { 
    synchronized (array) { 
     array[index] = value; 
    } 
    } 

    public int getValue(int index) { 
    synchronized (array) { 
     return array[index]; 
    } 
    } 

    ... 
} 
+1

+1: Bạn nên tạo một trường mà bạn đang sử dụng làm khóa 'final'. Nếu nó không thể là 'cuối cùng' bạn có thể có một lỗi. –

+0

Tôi chỉ cần thực hiện theo cách này, để viết bit đầu tiên của tôi về 'đồng bộ' mã và nó cố định lỗi của tôi, vì vậy thankyou. –

3

Từ khóa synchronized chỉ hoạt động với Đối tượng.

Đồng bộ hóa trên mảng chỉ khóa trên mảng (trong Java một mảng là một đối tượng).

Nếu bạn đồng bộ hóa trên một số phần tử riêng lẻ trong mảng, hãy lưu trữ chúng là các đối tượng chứ không phải nguyên thủy, đó là một khóa khác. Bạn có thể có cái không có cái kia, và ngược lại cũng đúng. Bạn không thể đồng bộ hóa trên nguyên thủy.

Nếu bạn cần phải ngăn chặn sửa đổi đồng thời mảng, đồng bộ hóa trên một số đối tượng trong mỗi truy cập vào mảng. Bạn có thể sử dụng bất kỳ đối tượng nào bạn muốn cho mục đích này, nhưng nó phải giống nhau cho điều cần làm việc. Lưu ý rằng nếu bạn truy cập tài nguyên được chia sẻ với đồng bộ hóa và trong các phần khác của mã bạn truy cập mà không đồng bộ hóa hoặc đồng bộ hóa trên đối tượng khác, thì điều đó rất hữu ích đối với không có gì.

1

Khi bạn đồng bộ hóa một đối tượng hoặc mảng, bạn đang ngăn chặn một chuỗi khác đồng bộ hóa so với cùng một đối tượng. Điều này không ngăn cản bạn sử dụng đối tượng và không hoạt động nào khác bị "khóa" Bạn phải đảm bảo bạn đã khóa đối tượng đầu tiên theo cách nhất quán để "khóa" đối tượng.

Các vấn đề liên quan