多线程详解

  1. 多线程

多线程是一种在实际编程当中很实用的编程手段和思路,但是多线程并不是只有优点,在使用多线程多过程当中,也会出现非常多的问题,这里我们做一个概括:

优点:

在大多数情况下,使用多线程可以充分的利用多核cpu的资源,极大的提升程序运行的效率。

缺点:

当某一个资源被多个线程共享时,这个资源可能会出现线程安全的问题。

当线程过多时,可能会因为程序编写不当等各种原因导致出现死锁,cpu负载过高的情况。

1.1线程安全

除去程序员编写不当的问题我们无法控制之外,解决线程安全问题就成了多线程程序编写最大的问题。

我们一句话概括什么是线程安全:

当多个线程同时 对同一个共享资源进行非原子操作(如 :修改某个共享资源的数据时),将会出现线程安全问题。

class Counter {
    private int count;
    public void increase() {
        ++this.count;
    }
    public int getCount() {
        return this.count;
    }}public class Main11 {
    private static final int CNT = 50000;
    private static final Counter counter = new Counter();
    public static void main(String[] args) throws InterruptedException {

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < CNT; i++) {
                counter.increase();
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int j = 0; j < CNT; j++) {
                counter.increase();
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println(counter.getCount());
    }}

以上是一个最简单的自增例子,我们预期的结果是两个线程各自增50000次,最后输出100000,但是结果总在变化且并不会出现我们预期的结果。

1.2类锁与对象锁

类锁和对象锁是Java中用于实现多线程同步的两种机制。‌

  • 对象锁(‌Object Lock)‌
    • 对象锁是基于对象实例的,‌每个对象都有一个与之关联的锁。‌当一个线程访问一个对象的synchronized方法或synchronized代码块时,‌它就获取了这个对象的锁。‌这意味着,‌如果一个对象有多个synchronized方法,‌同一时刻只有一个线程可以执行其中一个方法,‌因为这些方法共享同一个对象锁。‌对象锁的范围是对象实例级别的,‌不同对象实例的锁是互相独立的。‌一个线程获取了某个对象的锁并不影响其他对象实例的锁。‌
  • 类锁(‌Class Lock)‌
    • 类锁是基于类的,‌它是在类级别上实现的锁。‌当一个线程访问一个类的static synchronized方法或synchronized代码块时,‌它获取了该类的锁,‌而不是某个对象的锁。‌类锁的范围是整个类,‌无论有多少个类的实例,‌同一时刻只能有一个线程执行该类的synchronized方法或代码块。‌类锁在并发控制上更加广泛,‌适用于一些类级别的操作。‌

2.sync

2.1sync的锁类型:

对象锁:方法锁

方法锁是用synchronized修饰的一个类方法,作用方法即是方法作用域,除了这个方法要同步,其余不需要

public class SynchronizedObjectMethod implements Runnable{
    private static SynchronizedObjectMethod instance=new SynchronizedObjectMethod();
    public  synchronized void method(){
        System.out.println("我是对象锁的方法修饰符形式。我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    @Override
    public void run() {
        method();
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        thread1.start();
        thread2.start();
        while(thread1.isAlive()||thread2.isAlive()){
        }
        System.out.println("finish");
    }
}

对象锁:代码块形式

代码块锁就是常用的同步方法块,synchronized锁住的是它里面的对象,作用域就是synchonized{}里面的代码

public class SynchronizedObjectCodeBlock implements Runnable{
    private static SynchronizedObjectCodeBlock instance=new SynchronizedObjectCodeBlock();
    Object lock1=new Object();
    @Override
    public void run() {
        synchronized (lock1){
            System.out.println("我是对象锁的代码块形式。我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"运行结束");
        }

    }

    public static void main(String[] args){
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        thread1.start();
        thread2.start();
        while(thread1.isAlive()||thread2.isAlive()){
        }
        System.out.println("finish");
    }
}

类锁:class形式

class形式说的是synchronized()括号里使用的锁是class对象,所谓class对象指得是java文件对应的一个java.lang.class对象,所有该类生成的对象共有这个class对象 类加载机制,所以这个锁锁住了这个类生成的所有对象

public class SynchronizedClassClass implements Runnable{
    private static SynchronizedClassClass instance1=new SynchronizedClassClass();
    private static SynchronizedClassClass instance2=new SynchronizedClassClass();
    public void method(){
        synchronized (SynchronizedClassClass.class){
            System.out.println("我是类锁的形式之一:修饰.class。我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"运行结束");
        }
    }
    @Override
    public void run() {
        method();
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(instance1);
        Thread thread2 = new Thread(instance2);
        thread1.start();
        thread2.start();
        while(thread1.isAlive()||thread2.isAlive()){
        }
        System.out.println("finish");
    }
}

在这个案例中,存在两个SynchronizedClassClass对象,但是不能同时访问同步代码

类锁:static形式

static形式说的是static修饰synchronized修饰的方法,即static synchronized methodName,作用方法还是这个类的class对象

public class SynchronizedClassStatic implements Runnable{
    private static SynchronizedClassStatic instance1=new SynchronizedClassStatic();
    private static SynchronizedClassStatic instance2=new SynchronizedClassStatic();
    public static synchronized void method(){
        System.out.println("我是类锁的形式之一:加static修饰。我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public void  method2(){
        System.out.println("我是非静态方法,我叫"+Thread.currentThread().getName());
    }
    @Override
    public void run() {
        method();
        method2();
    }

    public static void main(String[] args) {
        Thread thread1 = new Thread(instance1);
        Thread thread2 = new Thread(instance2);
        thread1.start();
        thread2.start();
        while(thread1.isAlive()||thread2.isAlive()){
        }
        System.out.println("finish");
    }
}
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值