多线程编程之线程的同步机制(下): Synchronized同步代码块

简介: 上一篇文章讲了多线程编程中Synchronized同步方法的相关内容,Synchronized除了同步方法之外还可以同步语句块,这篇文章就介绍Synchronized如何同步语句块。

1 前言


上一篇文章讲了多线程编程中Synchronized同步方法的相关内容,Synchronized除了同步方法之外还可以同步语句块,这篇文章就介绍Synchronized如何同步语句块。


2 正文


1、Synchronized同步方法的缺点


在介绍Synchronized同步语句块之前,先来说说Synchronized同步方法的缺点。先看代码:


public class Demo9 {
    public static void main(String[] args) throws InterruptedException {
        Demo9Service service = new Demo9Service();
        Thread t1 = new Demo9ThreadA(service);
        t1.setName("A");
        Thread t2 = new Demo9ThreadA(service);
        t2.setName("B");
        t1.start();
        t2.start();
        Thread.sleep(20000);
        long start = Demo9Untils.start1 > Demo9Untils.start2 ? Demo9Untils.start2 : Demo9Untils.start1;
        long end = Demo9Untils.end1 > Demo9Untils.end2 ? Demo9Untils.end1 : Demo9Untils.end2;
        System.out.println("总耗时:" + (end - start) / 1000 + "秒");
    }
}
class Demo9Untils{
    static long start1;
    static long start2;
    static long end1;
    static long end2;
}
class Demo9Service{
    synchronized public void foo(){
        try{
            System.out.println("开始任务");
            Thread.sleep(5000);
            System.out.println("长时任务处理完成,线程" + Thread.currentThread().getName());
            System.out.println("结束任务");
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo9ThreadA extends Thread{
    public Demo9Service service;
    public Demo9ThreadA(Demo9Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo9Untils.start1 = System.currentTimeMillis();
        service.foo();
        Demo9Untils.end1 = System.currentTimeMillis();
    }
}
class Demo9ThreadB extends Thread{
    public Demo9Service service;
    public Demo9ThreadB(Demo9Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo9Untils.start2 = System.currentTimeMillis();
        service.foo();
        Demo9Untils.end2 = System.currentTimeMillis();
    }
}
复制代码


结果:


d228641caa3d4c00b125c191446d4d98~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


2、Synchronized同步代码块


再来看看synchronized同步代码块的代码:


public class Demo10 {
    public static void main(String[] args) {
        Demo10Service service = new Demo10Service();
        Thread t1 = new Demo10Thread(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo10Thread(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo10Service{
    public void foo(){
        try {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "开始于" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "结束于" + System.currentTimeMillis());
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo10Thread extends Thread{
    private Demo10Service service;
    public Demo10Thread(Demo10Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
复制代码


结果:


a89db19d5f6243a7bbf12da833d9537c~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


通过上面的示例可以发现Synchronized同步方法时间耗费过长。


3、使用同步代码块解决同块方法的问题


那么如何使用同步代码块解决同步方法的问题,代码如下:


public class Demo11 {
    public static void main(String[] args) throws InterruptedException {
        Demo11Service service = new Demo11Service();
        Thread t1 = new Demo11ThreadA(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo11ThreadB(service);
        t2.setName("B");
        t2.start();
        Thread.sleep(10000);
        long start = Demo11Utils.start1 > Demo11Utils.start2 ? Demo11Utils.start2 : Demo11Utils.start1;
        long end = Demo11Utils.end1 > Demo11Utils.end2 ? Demo11Utils.end1 : Demo11Utils.end2;
        System.out.println("耗时:" + (end - start) /1000 + "秒");
    }
}
class Demo11Utils{
    static long start1;
    static long start2;
    static long end1;
    static long end2;
}
class Demo11Service{
    /*synchronized*/ public void foo(){
        try {
            System.out.println(Thread.currentThread().getName() + "开始任务");
            Thread.sleep(3000);
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "处理计算结果");
            }
            System.out.println(Thread.currentThread().getName() + "结束任务");
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo11ThreadA extends Thread{
    private Demo11Service service;
    public Demo11ThreadA(Demo11Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo11Utils.start1 = System.currentTimeMillis();
        service.foo();
        Demo11Utils.end1 = System.currentTimeMillis();
    }
}
class Demo11ThreadB extends Thread{
    private Demo11Service service;
    public Demo11ThreadB(Demo11Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo11Utils.start2 = System.currentTimeMillis();
        service.foo();
        Demo11Utils.end2 = System.currentTimeMillis();
    }
}
复制代码


结果:


c67fd46be54c4a67906f8315a210a910~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


可见耗时明显缩短!


4、synchronized代码块间的同步


/**
 * synchronized代码块的同步
 */
public class Demo13 {
    public static void main(String[] args) throws InterruptedException {
        DemoService13 service13 = new DemoService13();
        Thread t1 = new Demo13Thread1(service13);
        t1.start();
        Thread.sleep(100);
        Thread t2 = new Demo13Thread2(service13);
        t2.start();
    }
}
//声明一个服务
class DemoService13{
    public void foo1(){
        //同步代码块
        synchronized (this){
            //睡眠2s
            try {
                System.out.println("foo1方法开始时间:"+System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("foo1方法结束时间:"+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void foo2(){
        synchronized (this){
            System.out.println("foo2方法开始时间: "+System.currentTimeMillis());
            System.out.println("foo2方法结束时间: "+System.currentTimeMillis());
        }
    }
}
//声明一个子线程
class Demo13Thread1 extends Thread{
    private DemoService13 service13;
    //构造方法
    public Demo13Thread1(DemoService13 service){
        this.service13 = service;
    }
    public void run(){
        service13.foo1();
    }
}
//再声明一个子线程
class Demo13Thread2 extends Thread{
    private DemoService13 service13;
    //构造方法
    public Demo13Thread2(DemoService13 service){
        this.service13 = service;
    }
    public void run(){
        service13.foo2();
    }
}
复制代码


结果:


534bea54003444fcbac4610e407d5ab1~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


使用同步synchronize(this)代码时需要注意,当一个线程访问object的一个synchronized(this)同步代码块时,其它线程对这个object的其它syncrhonized(this)同步的访问会被阻塞,说明synchronized使用的对象锁是同一个。


synchroinze(this)代码块锁定的是当前对象。比如:


/**
 *synchroinze(this)代码块是锁定当前对象
 */
public class Demo14 {
    public static void main(String[] args) throws InterruptedException {
        Demo14Service service = new Demo14Service();
        Thread t1 = new Demo14ThreadA(service);
        Thread t2 = new Demo14ThreadB(service);
        t2.start();
        Thread.sleep(10);
        t1.start();
    }
}
class Demo14Service{
    synchronized public void foo1(){
        System.out.println("foo1方法正在运行");
    }
    public void foo2(){
        try {
            synchronized (this) {
                System.out.println("foo2方法开始");
                Thread.sleep(2000);
                System.out.println("foo2方法结束");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo14ThreadA extends Thread{
    private Demo14Service service;
    public Demo14ThreadA(Demo14Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo1();
    }
}
class Demo14ThreadB extends Thread{
    private Demo14Service service;
    public Demo14ThreadB(Demo14Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
复制代码


结果:


b110d7e6d68148668c3ff8aac0c9447e~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


synchronized(this)代码块与synchronized方法一样,synchronized(this)代码块也是锁定当前对象的。


5、使用任意对象作为对象锁


除了可以使用syncrhonized(this)来同步代码块,java还支持任意对象作为对象锁来实现同步的功能。这个任意对象就是成员变量或者方法中的参数,语法格式为:


synchronized(lockobj)
复制代码


在多个线程持有的对象锁为同一个对象的情况下,同一时间只有一个线程可以执行synchoronized(lockobj)同步代码块中的代码。如果使用的不是同一个对象锁,运行的结果就是异步调用,交叉输出结果。


比如:


/**
 * 使用任意对象作为对象锁
 */
public class Demo15 {
    public static void main(String[] args) {
        Demo15Service service = new Demo15Service();
        Thread t1 = new Demo15Thread(service);
        t1.setName("线程1");
        t1.start();
        Thread t2 = new Demo15Thread(service);
        t2.setName("线程2");
        t2.start();
    }
}
class Demo15Service{
    //锁对象
    private Object lockobject = new Object();
    public void foo(){
        //synchronized锁定对象
        synchronized (lockobject){
            try {
                System.out.println(Thread.currentThread().getName() + "开始于" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "结束于" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Demo15Thread extends Thread{
    private Demo15Service service;
    public Demo15Thread(Demo15Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
复制代码


结果:


4c3d774b51b34387bd55d6c4d0f54f71~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


与synchronized (this)相比非tihs对象具有一定的优点。


一个类有很多个synchrnoized方法,虽然可以实现同步,但是会受到阻塞,影响运行效率。如果使用同步代码块非this对象,则synchronized非this对象的代码块中的程序与同步方法是不与其它的锁(this)争抢this锁,大大提高运行的效率。


/**
 * 非this对象具有的优点
 */
public class Demo16 {
    public static void main(String[] args) throws InterruptedException {
        Demo16Service service = new Demo16Service();
        Thread t1 = new Demo16ThreadA(service);
        t1.start();
        Thread.sleep(10);
        Thread t2 = new Demo16ThreadB(service);
        t2.start();
    }
}
class Demo16Service{
    private Object lockObject = new Object();
    public void foo(){
        try {
            synchronized (lockObject) {
                System.out.println("foo方法开始时间" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("foot方法结束时间" + System.currentTimeMillis());
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    synchronized public void foo2(){
        System.out.println("foo2方法开始时间" + System.currentTimeMillis());
        System.out.println("foo2方法结束时间" + System.currentTimeMillis());
    }
}
class Demo16ThreadA extends Thread{
    private Demo16Service service;
    public Demo16ThreadA(Demo16Service service){
        this.service  =service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
class Demo16ThreadB extends Thread{
    private Demo16Service service;
    public Demo16ThreadB(Demo16Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
复制代码


结果:


1b17fe741b664d3788cde7f8979fc99f~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


5、synchronized(非this对象)解决脏读


import java.util.ArrayList;
import java.util.List;
public class Demo17 {
    public static void main(String[] args) throws InterruptedException {
        Demo17List list = new Demo17List();
        Thread t1 = new Demo17ThreadA(list);
        t1.start();
        Thread t2 = new Demo17ThreadB(list);
        t2.start();
        Thread.sleep(5000);
        System.out.println("list size is " + list.size());
    }
}
class Demo17List{
    private List list = new ArrayList();
    synchronized public void add(Object obj){
        list.add(obj);
    }
    synchronized public int size(){
        return list.size();
    }
}
class Demo17Service{
    private Object lockObject = new Object();
    public void add(Demo17List list, Object obj){
        try {
            synchronized (list) {
                if (list.size() < 1) {
                    Thread.sleep(2000);
                    list.add(obj);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo17ThreadA extends Thread{
    private Demo17List list;
    public Demo17ThreadA(Demo17List list){
        this.list = list;
    }
    @Override
    public void run() {
        Demo17Service service = new Demo17Service();
        service.add(list, "a");
    }
}
class Demo17ThreadB extends Thread{
    private Demo17List list;
    public Demo17ThreadB(Demo17List list){
        this.list = list;
    }
    @Override
    public void run() {
        Demo17Service service = new Demo17Service();
        service.add(list, "b");
    }
}
复制代码


结果:


8781dbde3a924aacb2aea4de9a951067~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


对于synchronized(lockobj)格式的写法是将lockobj本身作为对象锁,总结上面的结果这样得出以下的结论:


a. 当多个线程同时执行syncrhonized(lockobj)同步代码块时结果是同步效果;


b. 当其它线程执行lockobj对象中的synchronized同步方法时也是同步效果;


c. 当其它线程执行lockobj对象方法里的synchronize(this)代码块时也是同步效果


如果其它线程调用不加synchronized关键字的方法时,还是异步调用。


6、半异步半同步


在并发模式中的同步和异步与IO模型中的同步和异步是完全不同的概念。


在IO模型中,同步和异步区分的是内核向应用程序通知的是何种IO事件(是就绪事件还是完成事件),以及该由谁来完成IO读写(是应用程序还是内核)。


而在并发模式中的同步指的是程序完全按照代码序列的顺序执行,异步指的是程序的执行需要由系统事件来驱动。常见的系统事件包括中断信号等。


按照同步方式运行的线程称为同步线程,按照异步方式运行的线程成为异步线程。显然异步线程的执行效率高,实时性强,这是很多嵌入式程序采用的模型。但编写异步方式执行的程序相对复杂,难于调试和扩展,且不适合大量的并发。而同步线程则相反,它虽然效率比较低,实时性较差,但逻辑简单。因此,对于某些既要求较好的实时性,又要求同时处理多个客户请求的应用程序,就可以同时使用同步线程和异步线程来实现。即使用半同步/半异步模式来实现!


如果使用synchronized关键字来实现半同步/半异步代码如下:


/**
 * 半同步和半异步
 */
public class Demo12 {
    public static void main(String[] args) {
        Demo12Service service = new Demo12Service();
        Thread t1 = new Demo12Thread(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo12Thread(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo12Service {
    public void foo(){
        try{
            for (int i = 0; i < 100; i++) {
                System.out.println("非同步线程" + Thread.currentThread().getName() + ", i=" + i);
                Thread.sleep(10);
            }
            System.out.println();
            synchronized (this){
                for (int i = 0; i < 100; i++) {
                    System.out.println("同步线程" + Thread.currentThread().getName() + ", i=" + i);
                    Thread.sleep(10);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo12Thread extends Thread{
    private Demo12Service service;
    public Demo12Thread(Demo12Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
复制代码


结果:


21c3a5ef074648fd8142bd6e13f8434b~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


不在synchronized块中的就是异步执行,在synchroinzed块中的代码就是同步执行。


非同步的输出是交叉的,而同步线程只有线程a执行完了才执行线程B。


7、synchronized同步静态方法与synchronized(class)代码块


前面讲了synchronized关键字修饰方法,但是并没有讲修饰静态方法,关键字synchronized还可以修饰静态方法,


synchronized修饰静态方法就是对象当前的*.java文件对应的Class进行加锁。比如:


public class Demo18 {
    public static void main(String[] args) {
        Thread t1 = new Demo18ThreadA();
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo18ThreadB();
        t2.setName("B");
        t2.start();
    }
}
class Demo18Service{
    synchronized public static void foo1(){
        System.out.println(Thread.currentThread().getName() + "进入方法foo1在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束方法foo1在" + System.currentTimeMillis());
    }
    synchronized public static void foo2(){
        System.out.println(Thread.currentThread().getName() + "进入方法foo2在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束方法foo2在" + System.currentTimeMillis());
    }
}
class Demo18ThreadA extends Thread{
    @Override
    public void run() {
        Demo18Service.foo1();
    }
}
class Demo18ThreadB extends Thread{
    @Override
    public void run() {
        Demo18Service.foo2();
    }
}
复制代码


结果:


13d958f5e3e5447e83c0db1480a5e4f7~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


从上面的结果可以发现在静态方法上使用synchronized修饰与在非静态方法上使用的结果是一致的,都是同步运行。但是其实从本质来讲它们是有区别的,在静态方法上使用synchronized是给Class类上锁,而在非静态方法上使用syncrhonized是给对象上锁。


public class Demo19 {
    public static void main(String[] args) {
        Demo19Service service = new Demo19Service();
        Thread t1 = new Demo19ThreadA(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo19ThreadB(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo19Service{
    synchronized public static void foo1(){
        System.out.println(Thread.currentThread().getName() + "进入foo1方法在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束foo1方法在" + System.currentTimeMillis());
    }
    synchronized public void foo2(){
        System.out.println(Thread.currentThread().getName() + "进入foo2方法在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束foo2方法在" + System.currentTimeMillis());
    }
}
class Demo19ThreadA extends Thread{
    private Demo19Service service;
    public Demo19ThreadA(Demo19Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
class Demo19ThreadB extends Thread{
    private Demo19Service service;
    public Demo19ThreadB(Demo19Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo1();
    }
}
复制代码


结果:


03b8d3e18fb94825a582add4d843c7d7~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


上面以异步方式运行的原因是因为持有锁是不一样的,非静态方法持有提对象锁,而静态方法持有的是Class锁,Class锁可以对类的所有对象实例起作用。


同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的


public class Demo20 {
    public static void main(String[] args) {
        Demo20Service service = new Demo20Service();
        Thread t1 = new Demo20ThreadA(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo20ThreadA(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo20Service{
    synchronized public static void foo1(){
        System.out.println(Thread.currentThread().getName() + "进入foo1方法在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束foo1方法在" + System.currentTimeMillis());
    }
    public static void foo2(){
        synchronized (Demo20Service.class) {
            System.out.println(Thread.currentThread().getName() + "进入foo1方法在" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "结束foo1方法在" + System.currentTimeMillis());
        }
    }
}
class Demo20ThreadA extends Thread{
    private Demo20Service service;
    public Demo20ThreadA(Demo20Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo1();
    }
}
class Demo20ThreadB extends Thread{
    private Demo20Service service;
    public Demo20ThreadB(Demo20Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
复制代码


结果:


60bb9e0ec3f04f5a97884f6390aabf98~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


8、synchronized(String)*


当使用synchronized关键字将String作为锁对象时:


public class Demo21 {
    public static void main(String[] args) {
        Thread t1 = new Demo21ThreadA();
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo21ThreadB();
        t2.setName("B");
        t2.start();
    }
}
class Demo21Service{
    public static void foo1(String lockObject){
        try {
            synchronized (lockObject) {
                while (true) {
                    System.out.println("线程" + Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public static void foo2(Object lockObject){
        try {
            synchronized (lockObject) {
                while (true) {
                    System.out.println("线程" + Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo21ThreadA extends Thread{
    @Override
    public void run() {
        Demo21Service.foo1("AA");
    }
}
class Demo21ThreadB extends Thread{
    @Override
    public void run() {
        Demo21Service.foo2("AA");
    }
}
复制代码


结果:


dca5eac83908416894950c9f0b63852b~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


通过上面结果可以发现只会打印线程B。只有线程B在运行的原因是,两个线程的对象锁都是使用AA,两个线程持有的相同的锁,所以造成线程B能运行。这就是String常量所带来的问题。所以不应该使用字符串类型作为对象锁,而应该使用其它类型,例如new Object(),对象就不会放入缓存 。


3 总结


多线程编程之线程的同步机制(上): Synchronized同步方法和本篇文章主要讲了在多线程编程中


Synchronized关键字对于同步机制的作用。Synchronized关键字不仅仅能够修饰方法还能够修饰代码块。

目录
相关文章
|
6天前
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
【6月更文挑战第20天】在Java多线程编程中,`synchronized`和`Lock`是两种关键的同步机制。`synchronized`作为内置关键字提供基础同步,简单但可能不够灵活;而`Lock`接口自Java 5引入,提供更复杂的控制和优化性能的选项。在低竞争场景下,`synchronized`性能可能更好,但在高并发或需要精细控制时,`Lock`(如`ReentrantLock`)更具优势。选择哪种取决于具体需求和场景,理解两者机制至关重要。
|
6天前
|
Java 测试技术
Java多线程同步实战:从synchronized到Lock的进化之路!
【6月更文挑战第20天】Java多线程同步始于`synchronized`关键字,保证单线程访问共享资源,但为应对复杂场景,`Lock`接口(如`ReentrantLock`)提供了更细粒度控制,包括可重入、公平性及中断等待。通过实战比较两者在高并发下的性能,了解其应用场景。不断学习如`Semaphore`等工具并实践,能提升多线程编程能力。从同步起点到专家之路,每次实战都是进步的阶梯。
|
6天前
|
Java 程序员
从0到1,手把手教你玩转Java多线程同步!
【6月更文挑战第20天】从0到1学Java多线程同步:理解线程同步关键,掌握`synchronized`用法,探索`Lock`接口,实战演练并进阶学习锁升级、`Condition`及死锁预防,成为多线程大师!
|
2天前
|
Java
Java中的`synchronized`关键字是一个用于并发控制的关键字,它提供了一种简单的加锁机制来确保多线程环境下的数据一致性。
【6月更文挑战第24天】Java的`synchronized`关键字确保多线程数据一致性,通过锁定代码块或方法防止并发冲突。同步方法整个方法体为临界区,同步代码块则锁定特定对象。示例展示了如何在`Counter`类中使用`synchronized`保证原子操作和可见性,同时指出过度使用可能影响性能。
12 4
|
1天前
|
存储 安全 Java
Java中的线程安全与同步技术
Java中的线程安全与同步技术
|
1天前
|
Java
java线程之信号同步
java线程之信号同步
7 0
|
2天前
|
Java
synchronized关键字在Java中为多线程编程提供了一种简便的方式来管理并发,防止数据竞争和死锁等问题
Java的`synchronized`关键字确保多线程环境中的数据一致性,通过锁定代码段或方法防止并发冲突。它可修饰方法(整个方法为临界区)或代码块(指定对象锁)。例如,同步方法只允许一个线程执行,同步代码块则更灵活,可锁定特定对象。使用时需谨慎,以避免性能影响和死锁。
9 0
|
5天前
|
安全 Java 开发者
Java多线程同步:synchronized与Lock的“爱恨情仇”!
【6月更文挑战第20天】Java多线程中,`synchronized`和`Lock`是线程安全的保障。`synchronized`简单易用,但有局限,如不可中断、无公平策略。`Lock`接口及`ReentrantLock`提供更细粒度控制,支持可中断、公平锁和条件变量,适合复杂场景。在选择时,应根据项目需求权衡简易性和灵活性。示例展示了两者用法差异,强调正确管理锁以避免死锁。理解特点,灵活应用,是多线程编程的关键。
|
5天前
|
存储 Linux C语言
c++进阶篇——初窥多线程(二) 基于C语言实现的多线程编写
本文介绍了C++中使用C语言的pthread库实现多线程编程。`pthread_create`用于创建新线程,`pthread_self`返回当前线程ID。示例展示了如何创建线程并打印线程ID,强调了线程同步的重要性,如使用`sleep`防止主线程提前结束导致子线程未执行完。`pthread_exit`用于线程退出,`pthread_join`用来等待并回收子线程,`pthread_detach`则分离线程。文中还提到了线程取消功能,通过`pthread_cancel`实现。这些基本操作是理解和使用C/C++多线程的关键。
|
7天前
|
安全 Java
【极客档案】Java 线程:解锁生命周期的秘密,成为多线程世界的主宰者!
【6月更文挑战第19天】Java多线程编程中,掌握线程生命周期是关键。创建线程可通过继承`Thread`或实现`Runnable`,调用`start()`使线程进入就绪状态。利用`synchronized`保证线程安全,处理阻塞状态,注意资源管理,如使用线程池优化。通过实践与总结,成为多线程编程的专家。