57.Java-线程安全之synchronized

同步代码块
  • 同步锁

为了保证每个线程都能正常执行原子操作,Java引入了线程同步机制。

同步监听对象/同步锁/同步监听器/互斥锁

对象的同步只是一个概念,可以想象为在对象上标记了一个锁

Java运行程序使用任何对象作为同步监听对象,但是一般我们把当前并发的同步资源作为同步监听对象

注意!在任何时候,最多允许一个线程拥有同步锁,谁拿到锁进入代码块,其他的线程只能在外面等着.

synchronized(this){
    //todo
}
class ImplementDemo implements Runnable{

    private int num = 50;
    
    public void run() {
        
        for (int i = 0;i<50;i++) {
            
            synchronized(this){
                
                if (num > 0) {
                    System.out.println(Thread.currentThread().getName() + "吃了编号为" + num +"的苹果" );
                    
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                    num--;
                }
            }
        
        }
        
    }
}

public class ExtendsDemo {
    
    public static void main(String[] args) {
        
        ImplementDemo im = new ImplementDemo();
        
        new Thread(im,"小A").start();
        new Thread(im,"小B").start();
        new Thread(im,"小C").start();
        
    }
    
}
同步方法

同步方法使用synchronized修饰的方法叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着.

此时的同步锁是谁:
对于非static方法,同步锁就是this
对于static方法,我们使用当前方法所在的类的字节码对象(ImplementDemo.class)

public synchronized void (){
    //todo
}
class ImplementDemo implements Runnable{

    private int num = 50;
    
    public void run() {
        
        for (int i = 0;i<50;i++) {
            
            eatMethod();
        }
        
    }
    
    public synchronized void eatMethod() {

        if (num > 0) {
            System.out.println(Thread.currentThread().getName() + "吃了编号为" + num +"的苹果" );
            
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            num--;
        }
    }
}

public class ExtendsDemo {
    
    public static void main(String[] args) {
        
        ImplementDemo im = new ImplementDemo();
        
        new Thread(im,"小A").start();
        new Thread(im,"小B").start();
        new Thread(im,"小C").start();
        
    }
    
}
synchronized的好与坏
  • 好处

保证了多线程并发访问时的同步操作,避免线程的安全性问题.

  • 缺点

使用synchronized的方法/代码块的性能比不用要低一些.

++建议尽量减小synchronized的作用域++

  • 举例StringBuffer与StringBuilder
public synchronized StringBuffer append(Object obj){
    super.append(String.valueOf(obj));
    return this;
}

public StringBuilder append(Object obj){
    return append(String.valueOf(obj));
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容