synchronized

经典面试题之:synchronized

一般说起Synchronized第一反应就是java锁,这次我们不从底层代码开始谈,而是先从Synchronized的用法上开始聊起来。
Synchronized可以作用在3个地方,分别是锁对象,锁方法,锁代码块

先看下Synchronized的一些用法

在方法上家Synchronized关键字
public class SysThread implements Runnable {

    private Integer i = 0;

    public  void addMyself() {
        int temp = i;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        temp++;
        i = temp;
        System.out.println(Thread.currentThread().getName() + ".." + i);

    }

    @Override
    public void run() {
        for (int j = 0; j < 5; j++)
            addMyself();
    }
}

public class SysThreadTest {

    public static void main(String[] args) {

        SysThread sysMainTest = new SysThread();

        Thread thread1 = new Thread(sysMainTest,"thread1");
        Thread thread2 = new Thread(sysMainTest,"thread2");
        thread1.start();
        thread2.start();

    }

}

这个是一个没有加Synchronized的代码,执行结果如下

thread2..1
thread1..1
thread1..2
thread2..2
thread1..3
thread2..3
....

这里我们可以发现在SysThread里面i被两个线程执行的时候,并没有按照我们的想法递增,因为在addMyself的时候发生了同步的问题

我们在addMyself的方法上家一个Synchronized,在看下

    public synchronized void addMyself() {
        ...
    }
    执行结果如下
    hread2..1
thread2..2
thread2..3
thread2..4
thread2..5
thread1..6
thread1..7
thread1..8
...

可以看到结果已经按照我们预先摄像的那样i做了自增操作。这是因为我们在方法上家了Synchronized,每次只允许一个线程进入该方法执行

在方法内的代码块增加Synchronized关键字,锁住i
synchronized (i) {
            int temp = i;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            temp++;
            i = temp;
            System.out.println(Thread.currentThread().getName() + ".." + i);
        }
        
执行结果如下
thread1..1
thread1..2
thread1..3
thread1..4
thread1..5
thread2..6
...

我们可以就看到执行结果和在方法上增加是一样的下效果

锁住对象,这里代码块里锁贼classs和在静态方法上增加Synchronized都属于锁对象的情况
public void addMyself() {
        synchronized (SysThread.class) {
           ...
        }
    }
    执行结果如下
    thread1..1
thread1..2
thread1..3
thread2..4
thread2..5
thread2..6
...

通过上面的几个例子,我们可以看到Synchronized可以起到锁的作用。

    public static void main(String[] args) {
          //锁代码块
        synchronized (SyncDemo1.class){
            System.out.println("this");
        }
    }

    //锁方法
    public synchronized void method1(){
        System.out.println("method1");
    }

    //锁静态方法
    public synchronized static void method2(){
        System.out.println("method2");
    }

以上代码执行javap -v xxx.class之后结果如下

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #2                  // Field lock:Ljava/lang/String;
         3: dup
         4: astore_1
         5: monitorenter
         6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         9: ldc           #4                  // String this
        11: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        14: aload_1
        15: monitorexit
        16: goto          24
        19: astore_2
        20: aload_1
        21: monitorexit
        22: aload_2
        23: athrow
        24: return
      Exception table:
         from    to  target type
             6    16    19   any
            19    22    19   any
      LineNumberTable:
        line 13: 0
        line 14: 6
        line 15: 14
        line 16: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  args   [Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 19
          locals = [ class "[Ljava/lang/String;", class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4

  public synchronized void method1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #6                  // String method1
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 19: 0
        line 20: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Ldemo7/SyncDemo1;

  public static synchronized void method2();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #7                  // String method2
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 23: 0
        line 24: 8
  1. 可以看到main方法中锁住代码块主要由以下指令实现 monitorenter, monitorexit,
    这里有两个monitorexit,主要是出现异常也可以退出monitor。
  2. 锁方法和静态方法我们可以看到flags,有ACC_SYNCHRONIZED标识。当执行到方法的时候,检测到有这个标志位,会隐式的调用monitorenter,monitorexit指令

synchronized的特性

  1. 可重入性,synchronized是偏向锁。
  2. 不可中断性,synchronized的实现是有字节码命令monitorenter, monitorexit实现的
  3. 有序性.synchronized是排他锁,在一定时间在只能有有一个线程执行synchronized修饰的方法或者代码块,根据as-if-serial语义,虽然synchronized无法禁止指令重排序,但是只有一个线程执行的话相当于单线程执行,执行结果必然是有序的。

Synchronized锁升级

围绕着synchronized还有一个问题就是优化,下图展示了一个synchronized的锁升级过程
右边图片是一个标准的锁过程,左边是引入的偏向锁的概念
java synchronized锁插图
引入偏向锁的概念是因为在实际的引用中很可能只有一个线程在执行代码。这种情况下可以减少使用轻量级锁带来的系统开销,因为轻量级依赖CAS操作。而偏向锁只需要在替换线程Id的时候使用CAS就可以了。
详细参考 wiki https://wiki.openjdk.java.net/display/HotSpot/Synchronization

  1. 一个线程进入后,检查对象头markword偏向标识是否偏向,如果是1,确认偏向锁执行偏向锁流程,进行加锁操作,存入线程id。
  2. 当发生多个线程争抢资源时,如果对象未锁定,会撤销偏向锁,将状态改成无锁状态,如果状态已锁定,将状态设置为轻量级锁状态
  3. 轻量级锁线程通过自旋等待资源。
  4. 如果自旋需要消耗cpu资源,自旋失败,无法获得对象会进行锁膨胀。升级为重量级锁
  5. 在发生STW的时候,会触发降级操作。判断如果当前对象没有被占用,则降级为轻量级锁

锁的标志位以及锁的状态,可以参考对象头的markword。
java synchronized锁插图1

3,877 对 “java synchronized锁”的想法;

  1. Hi I am so excited I found your weblog, I really found you by mistake, while I
    was looking on Askjeeve for something else, Anyhow I am here
    now and would just like to say thanks for a marvelous
    post and a all round thrilling blog (I also love the theme/design), I don’t have time to look over it all at the moment but I have saved it and also included your RSS feeds, so when I have time I will be back to
    read more, Please do keep up the great work.

  2. Pingback: leblogfm
  3. Instagram Takipçi Satın Almak Şirketler yada Şahıslar için Gerekli Midir?

    Kişisel sayfalar, firma sayfaları ya da farklı sebepler ile açılan sayfaların büyük kitlelere ulaşabilmesi açısından güvenilir
    takipçi satın alma işlemi önemli rol oynar.
    Bu şekilde hesapta olumlu değişiklikler görülür.
    Bu değişikliklerin başında tanınmak gelir
    ayrıca Instagram’da popüler olmak bir anlamda kazanç kapısı anlamı da taşır.

    Reklamlar, firmaların tanıtımı açısından yapılır.

    En önemli reklam da tanınan ve bilinen birinin yaptığı çalışmalar olur.

    Takipçisi yüksek bir hesap haline gelindiğinde büyük firmalar ile anlaşma yaparak sponsorluk
    alınabilir. Sponsorluk anlaşmaları sayesinde iyi miktarda para kazanılabilir.

    Instagram takipçi satın al mecrasında tanınmak ve bilinmek içintakipçi
    satın alişlemi sıklıkla uygulanır. Doğal yollar ile
    hesabı büyütmek uzun zaman ve büyük bir uğraş gerektirdiğinden takipçi kasma adına tercih edilen en etkili yöntem olan takipçi hizmeti
    ile hesap Instagram’ın keşfet alanına da düşer ve bu şekilde organik şeklide takipçi elde edilir.

  4. Takipçi Satın Almak Nedir?

    Pek çok kişinin takipçi sayın alma hizmetinden haberi olmadığını düşünerek bu yazıyı kaleme
    almak istedik. Özellikle sosyal medya hesapları
    üzerinden gerek satış
    yaparak gerekse de reklam gelirleri ile para kazanmak isteyen kişiler
    için takipçi sayısı oldukça önemlidir.
    Takipçi sayısı düşük olan bir hesabı takip etmek ister misiniz?

    Pek çok kişi bu soruya yanıt olarak hayır demektedir.
    Takipçi sayısı yüksek olan sosyal medya hesaplarının takip
    edilme şansı çok daha yüksektir. Bu nedenle oluşturduğunuz sosyal medya hesabınız
    için takipçi satın al hizmetleri sunulmaktadır.

    https://rebrand.ly/takipci-satin-al

  5. Instagram da Takipçi Satın Alarak Ek Gelir Sağlayabilirsin!

    İnstagram hesapları hem de önemli birer gelir kapısıdır.

    Özellikle reklam gelirleri biroldukça hesap sahibi için ek gelir oluşturmaktadır.

    şayet hesaplarınızda reklam alabilmek yahut Instagram üzerinden birşeyler satarak
    para
    kazanmaksa hedefiniz Türk gerçek takipçi paketlerini tercih etmelisiniz.

    Şayet bot yada bota benzer instagram takipçi satın alırsanız
    bunu gören hiç bir müşteri kitlesi size güvenmeyecektir.

    Hatta şunuda söylemekte fayda varki sizi takip
    etmek dahi istemeyebilirler.
    Bu sebepten sizleri kalitenin adresi olan takip201 e davet ediyoruz.

    En iyi Instagram takipçi satın alınabilir site.

    https://cutt.ly/instagramtakipcisatinal

  6. Welll therde are a few speciftic industries and business types which seem to move forward and prosper better than others so here is a list
    oof skme oof the top small business industries
    you may want too look at and why they are so successful.

    I didn’t understand thst statement when I started out.
    Also forums are great to discover your market as
    wrll – if there is a forum for your specific topic then the people oon the forum
    are moore or less your market and you can estimate the number
    off ‘customers’ your idea can generate by looking
    at the number of members on the forums.

  7. Hızla Yükselen Bir Fenomen Olmak İçin İnstagram Takipçi Satın Al
    Türkiye’nin en çok tanınan fenomenlerinin aylık ne kadar kazandığını biliyor musunuz?
    Peki, İnstagram takipçi satın al hizmeti sayesinde yüksek kazançlara ulaşmanın mümkün olduğunu?
    Eğer siz de bir sosyal medya fenomeni olmak istiyorsanız,
    doğru stratejiyi uyguladığınızdan emin olmalısınız.
    İşte, adım adım fenomen olmak için yapmanız gerekenler.

    https://u.to/h_NHGw İnstagram Takipçi Satın Al

  8. Instagram Takipçi Satın Almanızın İşleminin Hesaba Etkisi

    Takipçi almak, Instagram üzerinde popülerliği yakalamak isteyen hesapların kullandığı bir yöntemdir.

    Son zamanların gözde sosyal medya platformlarından olan Instagram,
    her geçen kendini yenileyip güncellemesi ile kullanıcı sayısını milyonlara ulaştırmıştır.

    Fotoğraf ve video paylaşma platformu olan zaman içinde
    firmaların e-ticaret alanına dönüşmüş ve insanlara ek
    gelir kapışı olmuştur.
    Instagram Takipçi Satın Almanın Profiliniz için Önemi

    Popülerlik ya da ek gelir isteyen kişiler için önemli hale gelen uygulamada bu
    başarıyı yakalamanın yolu takipçi
    sayısına bağlı olur. Intagram’ da yüksek takipçi sayısına sahip olmak
    ile pek çok insanın dikkatini çekmek daha kolay olur.

    Instagram’ da doğal yollar ile takipçi elde etmek diğer sosyal medya
    uygulamalarına göre daha zor olması nedeni ile
    Instagram takipçi satın al işlemine başvurulur. Bu işlem,
    hesabın daha öne çıkmasını sağladığı
    gibi daha fazla etkileşim almasına da yarar.

    Etkileşim alan bir hesap da Instagram keşfet alanına çıkar
    böylelikle daha çok takipçi hesabı takip etmeye başlar.

    https://rebrand.ly/takipz

  9. Kalıcı İnstagram Takipçi Satın Al : Kazanmaya Başla
    Takipçilerinizin kalıcı olmasını istiyorsanız, öncelikle İnstagram takipçi
    satın al sayfamızda yer alan gerçek takipçi paketlerimizden birini tercih etmelisiniz.

    Türk takipçilerin yer aldığı birbirinden ekonomik paketlerimiz ile
    siz de hızla büyüyen bir profile sahip olabilirsiniz.

    Düzenli İçerik Yüklediğinizden Emin Olun
    Bir sosyal medya platformunda fenomen olmak istiyorsanız, düzenli ve kaliteli içerik
    üretmelisiniz. Hedef kitlenizin yaş ve profiline uygun içerikler üretmek
    ve bunu düzenli şekilde yapmak sizin organik
    olarak yeni takipçiler kazanmanızı sağlar.

    Satın aldığınız takipçilerin de profilinizi ömür boyu takip etmesini
    istiyorsanız gönderilerinizin takipçilerinize uygun olduğundan emin olmalısınız.

    Takipçi Satın Al sende kazan

  10. Hey just wanted to give you a quick heads up. The words in your content seem to be
    running off the screen in Ie. I’m not sure if this is a formatting issue or something to do with web browser compatibility but I thought I’d post to let
    you know. The style and design look great though!
    Hope you get the problem solved soon. Kudos

  11. First off I want to say wonderful blog! I had a quick question which I’d
    like to ask if you do not mind. I was curious to know how you center yourself and clear your
    mind prior to writing. I have had difficulty clearing my
    mind in getting my ideas out there. I do enjoy writing but it just seems like the first 10 to 15 minutes are generally wasted simply just trying to figure out how to begin. Any recommendations or
    hints? Appreciate it!