1

我正在阅读最初来自(我相信)IBM developerworks 站点的线程教程。在其中,他们讨论了同步关键字以及同步代码块如何被实际对象锁定,而不是代码块本身。

例如,在下面的代码中,作者指出即使静态类 '<code>Thingie 的setLastAccess方法被列为同步,它下面定义的两个线程也可以setLastAccess同时调用,因为它们对 thingie 使用不同的值。但是,如果 thingie 是静态的,这是否意味着它们使用相同的值?

变量名是否只需要不同,即使它们指的是同一个对象?

public class SyncExample {
    public static class Thingie {
        private Date lastAccess;
        public synchronized void setLastAccess(Date date) {
            this.lastAccess = date;
        }
    }
    public static class MyThread extends Thread {
        private Thingie thingie;
        public MyThread(Thingie thingie) {
            this.thingie = thingie;
        }
        public void run() {
            thingie.setLastAccess(new Date());
        }
    }
    public static void main() {
        Thingie thingie1 = new Thingie(),
        thingie2 = new Thingie();
        new MyThread(thingie1).start();
        new MyThread(thingie2).start();
    }
} 
4

4 回答 4

6

您将静态方法与静态混淆了。如果setLastAccess是静态方法,那么如果它被标记为synchronized,它将锁定Class实例中的实例ClassLoader——每个加载器只有一个。如果该方法是静态且同步的,那么线程将锁定在同一个对象上。

但是,在您的示例中,Thingie 该类被标记为静态,而不是方法。上的 static 关键字意味着它Thingie不依赖于外部SyncExample类——这并不意味着只有一个实例Thingie并且它不影响同步。因此,在您的示例中,当setLastAccess被标记时synchronized,它锁定了类Thingiethis)的实例。由于有两个实例 (thingie1thingie2),因此锁位于不同的对象上。显然,如果两个线程都被传入,thingie1那么它们都将锁定在同一个对象上。

这里有一些阅读:

于 2011-10-18T18:11:02.327 回答
4

这段代码:

class SomeClass {
    public synchronized void setLastAccess(Date date) {
    }
}

是相同的:

class SomeClass {
    public void setLastAccess(Date date) {
        synchronized(this) {
        }
    }
}

而这段代码:

class SomeClass {
    public static synchronized void setLastAccess(Date date) {
    }
}

是相同的:

class SomeClass {
    public static void setLastAccess(Date date) {
        synchronized(SomeClass.class) {
        }
    }
}
于 2011-10-18T18:13:56.970 回答
0

如果同步方法是实例方法,则对每个对象进行锁定。因此,如果您有 2 个对象 obj1 和 obj2 ,它们可以在锁定自己的实例的情况下执行方法。

如果静态方法是同步的,则锁定在类对象上。因此,在执行第一个静态同步方法时,无法执行该方法以及任何其他静态方法。

于 2011-10-18T19:09:30.047 回答
0

很好的例子来解释java类中的静态同步。

我创建了一个名为“BookSeat”的方法,并使其同步。即使我使用同步关键字,但我仍然得到不一致的结果。为避免这种情况,只需在此方法中添加 static 关键字,您将获得正确的结果。

        package io.reactivestax.codepractice.mutithreading;
        class BookTheaterApp{
              static int total_seats=20;
                static synchronized void BookSeat(int ticket){
                if(total_seats>=ticket){
                    System.out.println(ticket+" Ticket booked successfully.");
                    total_seats=total_seats-ticket;
                    System.out.println("Seats left :"+total_seats);
                }else {
                    System.out.println("We cannot booked tickets ");
                    System.out.println("Required tickets: "+ticket);
                    System.out.println("Total tickets: "+total_seats);
                }
            }
        }

        class MyThread1 extends Thread{
            BookTheaterApp b1;
            int seats;
            MyThread1(BookTheaterApp b1,int seats){
                this.b1=b1;
                this.seats =seats;
            }
            @Override
            public void run(){
                b1.BookSeat(seats);
            }
        }

        class MyThread2 extends Thread{
            BookTheaterApp b2;
            int seats;
            MyThread2(BookTheaterApp b2,int seats){
                this.b2=b2;
                this.seats =seats;
            }
            @Override
            public void run(){
                b2.BookSeat(seats);
            }
        }

        public class StaticSynchro {
            public static void main(String[] args) {
                BookTheaterApp b1= new BookTheaterApp();
                MyThread1 t1= new MyThread1(b1,7);
                t1.start();
                MyThread2 t2= new MyThread2(b1,6);
                t2.start();
                BookTheaterApp b2= new BookTheaterApp();
                MyThread1 t3= new MyThread1(b2,5);
                t3.start();
                MyThread2 t4= new MyThread2(b2,7);
                t4.start();
            }
        }
于 2021-10-06T15:46:53.593 回答