synchronized用法

1.同时修饰方法和修饰对象this

java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。

 

java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,知道线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。

 

public class TestSynchronized

   public void test1()

   { 

        synchronized(this)

        { 

              int i = 5; 

              while( i-- > 0)

              { 

                   System.out.println(Thread.currentThread().getName()+ " : " + i); 

                   try

                   { 

                        Thread.sleep(500); 

                   }

                   catch (InterruptedExceptionie)

                   { 

                   } 

              } 

        } 

   } 

   public synchronized void test2()

   { 

        int i = 5; 

        while( i-- > 0)

        { 

             System.out.println(Thread.currentThread().getName() + " : " +i); 

              try

              { 

                   Thread.sleep(500); 

              }

              catch (InterruptedException ie)

              { 

              } 

        } 

   } 

   public static void main(String[] args)

   { 

        final TestSynchronized myt2 = new TestSynchronized(); 

        Thread test1 = new Thread(  newRunnable() {  public void run() {  myt2.test1(); }  }, "test1"  ); 

        Thread test2 = new Thread(  newRunnable() {  public void run() {myt2.test2();   }  }, "test2"  ); 

        test1.start();; 

        test2.start(); 

   }

}

 

 

test2 : 4

test2 : 3

test2 : 2

test2 : 1

test2 : 0

test1 : 4

test1 : 3

test1 : 2

test1 : 1

test1 : 0

这两个同步锁获得的是同一个内置对象锁

当取消test2的同步修饰时, 两个方法不会相互干扰, 所以synchronized只是一个内置锁的加锁机制,当某个方法加上synchronized关键字后,就表明要获得该内置锁才能执行,并不能阻止其他线程访问不需要获得该内置锁的方法

 

 

2.同时修饰静态方法和class类

public class TestSynchronized

   public void test1()

   { 

        synchronized(TestSynchronized.class)

        { 

              int i = 5; 

              while( i-- > 0)

              { 

                   System.out.println(Thread.currentThread().getName()+ " : " + i); 

                   try

                   { 

                        Thread.sleep(500); 

                   }

                   catch (InterruptedExceptionie)

                   { 

                   } 

              } 

        } 

   } 

   public static synchronized void test2()

   { 

        int i = 5; 

        while( i-- > 0)

        { 

             System.out.println(Thread.currentThread().getName() + " : " +i); 

              try

              { 

                   Thread.sleep(500); 

              }

              catch (InterruptedException ie)

              { 

              } 

        } 

   } 

   public static void main(String[] args)

   { 

        final TestSynchronized myt2 =new TestSynchronized(); 

        Thread test1 = new Thread(  newRunnable() {  public void run() {  myt2.test1(); }  }, "test1"  ); 

        Thread test2 = new Thread(  newRunnable() {  public void run() {TestSynchronized.test2();   }  }, "test2"  ); 

        test1.start(); 

        test2.start();      }

}

 

test1 : 4

test1 : 3

test1 : 2

test1 : 1

test1 : 0

test2 : 4

test2 : 3

test2 : 2

test2 : 1

test2 : 0

其实,类锁修饰方法和代码块的效果和对象锁是一样的,因为类锁只是一个抽象出来的概念,只是为了区别静态方法的特点,因为静态方法是所有对象实例共用的,所以对应着synchronized修饰的静态方法的锁也是唯一的,所以抽象出来个类锁

 

3.同时修饰静态方法和普通方法

synchronized同时修饰静态方法和实例方法,但是运行结果是交替进行的,这证明了类锁和对象锁是两个不一样的锁,控制着不同的区域,它们是互不干扰的

 

4.同步方法的缺陷

既然有了synchronized修饰方法的同步方式,为什么还需要synchronized修饰同步代码块的方式呢?而这个问题也是synchronized的缺陷所在


 synchronized的缺陷:当某个线程进入同步方法获得对象锁,那么其他线程访问这里对象的同步方法时,必须等待或者阻塞,这对高并发的系统是致命的,这很容易导致系统的崩溃。如果某个线程在同步方法里面发生了死循环,那么它就永远不会释放这个对象锁,那么其他线程就要永远的等待。这是一个致命的问题。

 
当然同步方法和同步代码块都会有这样的缺陷,只要用了synchronized关键字就会有这样的风险和缺陷。既然避免不了这种缺陷,那么就应该将风险降到最低。这也是同步代码块在某种情况下要优于同步方法的方面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值