Nếu luồng T1 vào phương thức m1 bằng cách lấy khóa cấp lớp, điều này có nghĩa là một luồng T2 khác không thể chạy phương thức khác m2 bằng cách lấy khóa mức đối tượng không?Khóa cấp độ Java so với khóa cấp đối tượng
Trả lời
Không, điều đó không có nghĩa là. "Khóa cấp độ lớp" chỉ là một khóa thông thường trên một đối tượng khác, cụ thể là SomeClass.class
. Khóa "khóa mức đối tượng" khóa trên this
.
Edit: Chỉ cần chắc chắn rằng tôi đang theo sự hiểu biết của bạn về các thuật ngữ, bạn đang tự hỏi nếu m1 và m2 có thể chạy đồng thời khi chúng được định nghĩa dưới đây:
public class SomeClass {
public synchronized static void m1() {
//do something
}
public synchronized void m2() {
//do something
}
}
Và câu trả lời là có, m1 và m2 có thể chạy đồng thời. Nó có chức năng tương đương với điều này:
public class SomeClass {
public static void m1() {
synchronized (SomeClass.class) {
//do something
}
}
public void m2() {
synchronized (this) {
//do something
}
}
}
Vì chúng đang đồng bộ hóa trên các đối tượng hoàn toàn khác nhau, chúng không loại trừ lẫn nhau.
Trong java có hai loại ổ khóa:
- Lớp Cấp
- Object Cấp
Trong trường hợp các phương pháp tĩnh khóa luôn kiểm tra trên lớp nhưng trong trường hợp sơ thẩm phương pháp khóa luôn được kiểm tra trên đối tượng.
Ví dụ:
show1()
là phi tĩnh và show()
là tĩnh. Bây giờ, show()
được gọi bằng tên lớp (hoặc theo đối tượng) và show1()
được gọi theo đối tượng, sau đó cả hai phương pháp có thể truy cập đồng thời bởi hai luồng.
class Shared{
static int x;
static synchronized void show(String s,int a){
x=a;
System.out.println("Starting in method "+s+" "+x);
try{
Thread.sleep(2000);
}
catch(Exception e){ }
System.out.println("Ending from method "+s+" "+x);
}
synchronized void show1(String s,int a){
x=a;
System.out.println("Starting show1 "+s);
try{
Thread.sleep(2000);
}
catch(Exception e){ }
System.out.println("Ending from show1 "+s);
}
}
class CustomThread extends Thread{
Shared s;
public CustomThread(Shared s,String str){
super(str);
this.s=s;
start();
}
public void run(){
Shared.show(Thread.currentThread().getName(),10);
}
}
class CustomThread1 extends Thread{
Shared s;
public CustomThread1(Shared s,String str){
super(str);
this.s=s;
start();
}
public void run(){
s.show1(Thread.currentThread().getName(),20);
}
}
public class RunSync {
public static void main(String[] args) {
Shared sh=new Shared();
CustomThread t1=new CustomThread(sh,"one");
CustomThread1 t2=new CustomThread1(sh,"two");
}
}
Output:
Starting in method one 10
Starting show1 two
Ending from method one 20
Ending from show1 two
mức Object khóa:
Object cấp khóa là cơ chế khi bạn muốn đồng bộ hóa một khối mã phương pháp không tĩnh hay không tĩnh như vậy mà chỉ một thread sẽ có thể thực thi khối mã trên cá thể đã cho của lớp. Điều này nên luôn luôn được thực hiện để làm cho thread dữ liệu cấp độ thể hiện an toàn. Điều này có thể được thực hiện như sau:
public class DemoClass
{
public synchronized void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (this)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
Lớp cấp khóa:
Lớp cấp khóa ngăn ngừa nhiều chủ đề để vào trong khối đồng bộ trong bất kỳ tất cả các trường có sẵn trên runtime. Điều này có nghĩa là nếu trong thời gian chạy có 100 phiên bản của DemoClass, thì chỉ có một luồng sẽ có thể thực thi demoMethod() trong bất kỳ trường hợp nào tại một thời điểm và tất cả các phiên bản khác sẽ bị khóa cho các luồng khác. Điều này nên luôn luôn được thực hiện để làm cho luồng dữ liệu tĩnh an toàn.
public class DemoClass
{
public synchronized static void demoMethod(){}
}
or
public class DemoClass
{
public void demoMethod(){
synchronized (DemoClass.class)
{
//other thread safe code
}
}
}
or
public class DemoClass
{
private final static Object lock = new Object();
public void demoMethod(){
synchronized (lock)
{
//other thread safe code
}
}
}
Ví dụ để hiểu đối tượng và trình độ lớp khóa trong Java
1) Object Cấp dụ khóa
package com.test;
public class Foo implements Runnable {
@Override
public void run() {
Lock();
}
public void Lock() {
System.out.println(Thread.currentThread().getName());
synchronized(this) {
System.out.println("in block " + Thread.currentThread().getName());
System.out.println("in block " + Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Foo b1 = new Foo();
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b1);
Foo b2 = new Foo();
Thread t3 = new Thread(b2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
đầu ra:
t1
t3
t2
in block t3
in block t1
in block t3 end
in block t1 end
in block t2
Lưu ý rằng t3 sẽ không chặn khi chuỗi t1 và t2 bị chặn. Bởi vì khóa được đặt trên đối tượng này và đề t3 có khác nhau đối tượng này hơn chủ đề t1, t2
2) Lớp Cấp khóa dụ
Các mã trong khóa cấp độ đối tượng, chỉ Foo.class là được thêm vào trong khối được đồng bộ hóa. Tất cả các chủ đề đang được tạo ra bằng cách sử dụng đối tượng của lớp Foo sẽ bị chặn.
package com.test;
public class Foo implements Runnable {
@Override
public void run() {
Lock();
}
public void Lock() {
System.out.println(Thread.currentThread().getName());
synchronized(Foo.class) {
System.out.println("in block " + Thread.currentThread().getName());
System.out.println("in block " + Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Foo b1 = new Foo();
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b1);
Foo b2 = new Foo();
Thread t3 = new Thread(b2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
đầu ra:
t1
t3
in block t1
in block t1 end
t2
in block t3
in block t3 end
in block t2
in block t2 end
khối đồng bộ sẽ được thực hiện đối với các chủ đề tương tự.
Có thể cả phương pháp đồng bộ hóa tĩnh và không đồng bộ tĩnh đều có thể chạy đồng thời hoặc đồng thời vì chúng khóa trên đối tượng khác.
khóa mức Class được thực hiện bằng từ khóa "tĩnh đồng bộ, trong khi đó mức đối tượng được thực hiện chỉ bằng từ khóa synchronized. Object khóa cấp độ được thực hiện để hạn chế tương tự đối tượng để vận hành thông qua chủ đề khác nhau, trong đó khi khóa cấp độ được thực hiện để hạn chế bất kỳ đối tượng nào hoạt động.
Những cách khác nhau có trình độ lớp khóa: 1) public class DemoClass {
public static synchronized void demoMethod(){
//dosomething
}
}
2)
public class DemoClass {
public void demoMethod(){
synchronized(DemoClass.class){
//dosomething
}
}
}
3)
public class DemoClass {
private final static Object lock = new Object();
public void demoMethod(){
synchronized(lock){
//dosomething
}
}
}
Cách này trả lời câu hỏi? – shmosel
khóa mức Class và dụ mức khóa cả hai đều khác nhau. Cả hai đều không ảnh hưởng đến trạng thái khóa khác. Nếu một phiên bản của một lớp đã bị khóa bởi một luồng thì một luồng khác sẽ không thể khóa cho cá thể đó cho đến khi trừ khi khóa được giải phóng bởi chuỗi đầu tiên. Hành vi tương tự có ở đó để khóa cấp độ lớp.
Nhưng nếu một chủ đề mua khóa cấp Lớp thì một luồng khác có thể lấy khóa trên một trong các thể hiện của nó. Cả hai có thể làm việc parallel.`
package lock;
class LockA implements Runnable {
@Override
public void run() {
synchronized (LockA.class) {
System.out.println("Class");
try {
Thread.sleep(60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestClassVsInstanceLock {
public static void main(String[] args) {
final LockA a = new LockA();
final LockA b = new LockA();
try {
Thread t = new Thread(a);
Thread t1 = new Thread() {
@Override
public void run() {
synchronized (b) {
System.out.println("Instance 1"+ currentThread().currentThread().holdsLock(b));
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
t1.start();
synchronized (a) {
System.out.println("Instance2");
Thread.sleep(10 * 1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
'
này sẽ in: - Instance2 Lớp Instance 1true
Tất cả sẽ được in ngay lập tức mà không cần bất kỳ tạm dừng.
Nếu thread T1 nhập phương thức m1 bằng cách lấy khóa cấp lớp, điều này có nghĩa là một luồng T2 khác không thể chạy phương thức khác m2 bằng cách lấy khóa mức đối tượng không?
Khóa cấp đối tượng và Khóa cấp lớp khác nhau. Trong trường hợp trên, T2 có thể chạy phương thức m2 bằng cách lấy khóa mức đối tượng. Nhưng nếu m2 là static synchronized
, T2 không thể gọi phương thức m2 trừ khi khóa cấp phát hành lớp T1 trên phương thức m1.
Nó không phải là có thể cho hai lời gọi của synchronized
phương pháp trên cùng một đối tượng để interleave. Khi một luồng đang thực hiện phương thức synchronized
cho một đối tượng, tất cả các luồng khác gọi phương thức synchronized
cho cùng một khối đối tượng (tạm dừng thực hiện) cho đến khi chuỗi đầu tiên được thực hiện với đối tượng.
Giả sử rằng bạn có hai phương thức synchronized
m1 và m2 trên đối tượng O. Nếu luồng T1 đang ở giữa thực hiện phương pháp m1, thì T2 phải đợi để gọi phương thức m2 trên cùng đối tượng O trừ khi khóa bản phát hành luồng T1 trên phương pháp m1.
Chủ đề mua lại các khóa nội tại cho đối tượng Class
gắn liền với lớp. Do đó quyền truy cập vào các trường static
của lớp được điều khiển bởi một khóa khác với khóa cho bất kỳ trường hợp nào của lớp.
Giả sử phương thức m1 là static synchrnozed
và phương pháp m2 cũng là static synchronized
và bạn có hai đối tượng khác nhau o1 và o2.
Nếu chủ đề T1 đang ở giữa thực hiện phương pháp m1 trên đối tượng o1, thì T2 phải chờ để gọi phương thức m2 trên đối tượng o2 trừ khi bản phát hành Thread T1 khóa trên phương thức m1.
- 1. Khóa mutex phân cấp trong Java
- 2. Khóa XSD/keyref: cấu trúc khóa phân cấp
- 3. Tìm kiếm thuật toán khóa cấp phép
- 4. Tại sao HashMap lại phục hồi mã băm do đối tượng khóa cung cấp?
- 5. Tạo đối tượng Java bằng cặp khóa/giá trị?
- 6. Các luồng Java đang chờ khóa đối tượng không bị khóa (hiển nhiên) bị khóa
- 7. Siêu khóa so với khóa Ứng viên
- 8. Chặn khóa so với khóa không chặn
- 9. Mật mã .NET cho khóa cấp phép?
- 10. Cung cấp kho khóa cho webService client
- 11. Các khóa từ điển Python (so sánh các đối tượng lớp) với nhiều so sánh
- 12. quyền đối tượng cấp django
- 13. python JSON chỉ nhận được khóa ở cấp độ đầu tiên
- 14. Khóa trên một đối tượng
- 15. Đối tượng làm khóa băm
- 16. C# luồng - Khóa đối tượng
- 17. Identifer so với từ khóa
- 18. Lớp khóa nào phù hợp để sắp xếp thứ cấp?
- 19. Sử dụng request.getSession() làm đối tượng khóa?
- 20. Quyền đối tượng cấp khung đối tượng Django REST
- 21. Đặt lại kích hoạt Windows/Xóa khóa cấp phép
- 22. Đối tượng java.sql.Connection cung cấp là null
- 23. So sánh tốc độ truy cập từ điển với phím số nguyên so với khóa chuỗi
- 24. Chế độ gỡ lỗi không dây của Phonegap và ký bằng khóa cấp phép
- 25. Thay đổi bảng để cung cấp ràng buộc khóa ngoài
- 26. Cung cấp Node.JS webapp "chìa khóa trong tay"
- 27. Mongo: truy vấn bằng khóa một cấp sâu
- 28. Tổng hợp khóa chính, khóa ngoài. Tham chiếu đến đối tượng hoặc khóa?
- 29. Cách cất giữ khóa công khai trong ngăn chứa khóa RSA cấp máy
- 30. Nhiều đối tượng khóa cần thiết?
nếu cả hai phương pháp được khai báo là tĩnh thì sao? Tôi tin rằng trong trường hợp đó, cả hai sẽ trở nên loại trừ lẫn nhau, đúng không? – buch11
@ buch11: Đúng vậy, nó sẽ giống như cả hai đang làm 'đồng bộ (SomeClass.class) {...}', và chặn bất kỳ kịch bản tải lớp phức tạp nào, đây sẽ là cùng một đối tượng trong cả hai trường hợp. Về mặt kỹ thuật, việc nạp lớp cho phép bạn có hai "tải trọng" riêng biệt của cùng một lớp và bạn có thể chạy các phương thức đồng bộ tĩnh trong các lớp khác nhau song song. Nhưng ngăn chặn sự vui nhộn đó, nó loại trừ lẫn nhau. –
Bạn có thể tự hỏi điều gì xảy ra khi một phương thức đồng bộ hóa tĩnh được gọi, vì một phương thức tĩnh được liên kết với một lớp, không phải là một đối tượng. Trong trường hợp này, thread thu được khóa nội tại cho đối tượng Class được liên kết với lớp đó. ** Do đó truy cập vào các trường tĩnh của lớp được điều khiển bởi một khóa khác với khóa cho bất kỳ cá thể nào của lớp. ** [Nguồn] (https://docs.oracle.com/javase/tutorial/essential/concurrency /locksync.html) – Eduardo