线程的生命周期之线程同步

如你所知,当使用多个线程访问同一个数据时,如果没有同步机制,很容易出现线程安全问题,可能会导致数据不一致,甚至会出现死锁的情况。因此,线程同步是保证程序正确性和性能的重要手段。

可以在程序中加入同步代码块使线程同步,同步代码块的语法格式如下:

复制代码
synchronized(obj)
{
  ...
  //此处的代码就是同步代码块
}

这里是一个简单的 Java 多线程代码段,使用同步块来确保线程安全:

复制代码
public class SynchronizedThread implements Runnable {
    private int count;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + ": " + count);
                count++;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        SynchronizedThread synchronizedThread = new SynchronizedThread();
        Thread thread1 = new Thread(synchronizedThread);
        Thread thread2 = new Thread(synchronizedThread);
        thread1.start();
        thread2.start();
    }
}

在这个例子中,我们创建了一个名为 SynchronizedThread 的类,它实现了 Runnable 接口,并覆盖了 run() 方法。在 run() 方法中,我们使用同步块来确保线程安全。synchronized 关键字将代码块标记为同步,并使用 this 作为互斥锁对象。

我们还创建了两个线程 thread1 和 thread2 ,它们共享同一个 SynchronizedThread 实例,并同时运行。由于我们使用了同步块,这两个线程在访问共享变量 count 时不会发生竞争条件。

Java 多线程安全还可以使用同步方法,同步方法就是使用 synchronized 关键字来修饰某个方法,则该方法为同步方法,通过使用同步方法可以使该方法被多个线程安全地访问。

以下是一个使用同步方法的例子:

复制代码
public class SynchronizedExample {

    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }

    public static void main(String[] args) {
        SynchronizedExample example = new SynchronizedExample();

        // create multiple threads
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    example.increment();
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    example.increment();
                }
            }
        });

        // start the threads
        thread1.start();
        thread2.start();

        // wait for the threads to finish
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // print the final count
        System.out.println("Final count: " + example.getCount());
    }
}

这个例子中,我们定义了一个类 SynchronizedExample ,其中有一个计数器 count 。我们使用 synchronized 关键字来定义了两个同步方法 increment() 和 getCount() ,以确保多个线程不能同时访问这两个方法。

在 main() 方法中,我们创建了两个线程,并分别启动它们。每个线程都会执行 1000 次 increment() 方法,以增加计数器的值。

最后,我们等待这两个线程完成,然后打印最终的计数器值。由于这两个线程是同步执行的,所以最终的计数器值应该是 2000 。

相关推荐
咩咩啃树皮2 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
灯澜忆梦2 小时前
GO_并发编程---定时器
开发语言·后端·golang
鱟鲥鳚2 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
-银雾鸢尾-2 小时前
C#中的StringBuilder相关方法
开发语言·c#
-银雾鸢尾-3 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白4 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司4 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地5 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun3141595 小时前
TCP超时重传机制是为了解决什么问题?
java
段一凡-华北理工大学6 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化