synchronized的注意事项和项目中的应用方案

Synchronized锁注意事项

synchronized关键字,用它来修饰需要同步的方法和需要同步代码块,默认是当前对象作为锁的对象。在修饰类时(或者修饰静态方法),默认是当前类的Class对象作为所的对象故存在着方法锁、对象锁、类锁 这样的概念

在使用到锁的时候有锁方法,锁对象,和锁类,那么Synchronized是如何实现这三种方法的?

对象锁

修饰在方法上,多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)

public synchronized void obj() {
  System.out.println("w");          
 }

修饰代码块,这个this就是指当前对象(类的实例),多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)

public void obj2() {
   synchronized (this) {
     System.out.println("w");
         
   }
 }


public void obj2() {
   String str=new String("lock");//在方法体内,调用一次就实例化一次,多线程访问不会阻塞,因为不是同一个对象,锁是不同的
   synchronized (str) {
       System.out.println("w");
   }
 }

String str=new String("lock"); //对象放在方法外,调用方法的时候不会新创建一个对象。
 public void obj2() {
   synchronized (str) {
       System.out.println("w");
   }
  }

Synchronized类锁

Synchronized修饰静态的方法

public static synchronized void obj3() {
       System.out.println("w");
 }

synchronized (test.class) ,锁的对象是test.class,即test类的锁

public void obj1() {
    synchronized (test.class) {
       System.out.println("w");
   }
 }

在一个类中有两方法,分别用synchronized 修饰的静态方法(类锁)和非静态方法(对象锁)。多线程访问两个方法的时候,线程会不会阻塞?

public static synchronized void obj3() {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
   }

 public synchronized void obj4() {
       int i = 5;
       while (i-- > 0) {
           System.out.println(Thread.currentThread().getName() + " : " + i);
           try {
               Thread.sleep(500);
           } catch (InterruptedException ie) {
           }
       }
   }

输入如下:

Thread-0 : 4
Thread-1 : 4
Thread-0 : 3
Thread-1 : 3
Thread-1 : 2
Thread-0 : 2
Thread-1 : 1
Thread-0 : 1
Thread-1 : 0
Thread-0 : 0

因此是不会发生阻塞的!!!

总结

1.要满足方法同步(或者代码块同步)就必须保证多线程访问的是同一个对象(在java内存中的地址是否相同)。

2.类锁和对象锁同时存在时,多线程访问时不会阻塞,因为他们不是一个锁。

理论一摞摞,实际在开发中如何使用Synchronized保证线程安全呢?

在项目中的应用方案

注意:我们通常说的并发容器如ConcurrentHashMap等,都说是并发安全的,以为应用了上了这些容器就能保证线程的安全!我想说的是这些容器是能保证其变量的线程安全(也就是增删盖查多线程操作此变量下都是安全的),但是并不能保证业务上的并发安全问题。要想保证业务上的并发问题还是需要使用锁机制来控制业务并发问题!

在java中并发数据的发生基本都是操作一个类中成员变量,因此,我们需要在B类中对A类进行操作,那么我们假如是要控制A对象中的操作并发问题就需要将A的整个对象进行加锁,防止其他线程对同一个A对象进行操作(当然,其他线程对A类的不同对象可以并发操作并不会产生阻塞问题,也不会发生线程安全问题,这个是允许的)。因此使用上面的对象锁即可。也就是在B类中操作的A对象的成员变量,放到A对象中的方法上并加上synchronized即可保证线程安全。这样也能将锁细化。

在项目中,我们就是这样来控制和细化并发问题的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
synchronizedJava 用来实现线程同步的关键字。使用 synchronized 关键字可以保证同一时间只有一个线程执行被 synchronized 修饰的代码块或方法,从而避免多个线程同时访问共享资源而引发的数据竞争和不一致性的问题。 以下是使用 synchronized 时需要注意的事项: 1. 的粒度要合理,住尽可能少的代码。如果住的代码过多,会降低程序的并发性能。 2. 避免死。当有多个线程竞争多个时,如果顺序不当,可能会出现死的情况。 3. 避免过多的竞争。当多个线程竞争同一个时,会降低程序的并发性能,因此需要尽量减少竞争的情况。 4. synchronized 修饰的方法或代码块尽量简单。如果一个方法或代码块包含太多的逻辑和操作,那么住它的时候会影响其他线程的执行速度。 5. 尽量避免在 synchronized调用外部方法,特别是未知的方法。这可能会导致住的时间变长,从而影响程序的性能。 6. 不要在循环使用 synchronized。这会导致住的时间过长,从而降低程序的性能。 7. 在使用 synchronized 时,要考虑到线程安全问题,避免出现线程安全问题,例如在多个线程访问同一对象的时候,可能会出现对象状态不一致的问题。 以上是使用 synchronized 时需要注意的事项。为了避免出现问题,应该合理使用 synchronized 关键字,注意的粒度和竞争的情况,避免死和线程安全问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值