Java多线程之synchronizedvolatile基础篇

Izellah ·
更新时间:2024-11-10
· 796 次阅读

什么是线程 线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
                          ——百度百科 一、实现线程的几种方式 继承Thread类重写run()方法 public class ThreadDemo { public static void main(String[] args) { MyThread myThread = new MyThread(); /*开启线程*/ myThread.start(); } } class MyThread extends Thread{ @Override public void run() { // 写入自己的功能代码 } } 实现Runnable接口 public class RunnableDemo { public static void main(String[] args) { /*通过实现Runnable接口开启多线程*/ MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); /*通过匿名内部类实现*/ new Thread(()-> { // 写入自己的功能代码 }).start(); new Thread(()-> System.out.println("线程4")).start(); new Thread(()-> System.out.println("线程5")).start(); } } class MyRunnable implements Runnable{ @Override public void run() { // 写自己的功能代码 } } 线程常用方法详解
Thread.currentThread()获取当前正在执行此代码的线程信息 public class MyThread { public static void main(String[] args) { /** * ()->{ * // 获取当前线程信息 * Thread thread = Thread.currentThread(); * System.out.println(thread.toString()); *} * 此处相当于传了一个实现了Runnable接口类的对象 * */ new Thread(()->{ Thread thread = Thread.currentThread(); System.out.println(thread.toString()); }).start(); } }

Thread.currentThread().isAlive()判断线程是否处于活动状态

public class MyThread { public static void main(String[] args) { new Thread(()->{ System.out.println(Thread.currentThread().isAlive()); }).start(); } }

Thread.sleep(5000);使当前线程进行休眠

public class MyThread { /*HelloWorld需要等待5s才能被打印*/ public static void main(String[] args) { new Thread(()->{ try { /*线程休眠*/ Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("HelloWorld"); }).start(); } } 二、实现锁的几种方式

synchronized

synchronized锁定的是对象,而不是代码块,synchronized是可以重入锁,当程序出现异常时会释放锁 public class MyThread { private static Object object = new Object(); public static void main(String[] args) { /*此处锁的是object对象*/ synchronized (object){ // 功能代码 } } /*此处锁定的是当前对象*/ public synchronized void m(){ } /*在没有new MyThread类对象时使用m1()方法,锁的是MyThread.class 对象*/ public static synchronized void m1(){ } /*可重人锁,当线程获取到了执行demo1方法的对象锁,当执行到demo2()时也能获取到对象锁*/ public synchronized void demo1(){ // 功能代码 demo2(); } public synchronized void demo2(){ } }

synchronized底层原理(升级锁)

第一个线程进入的时候是偏向锁,所谓偏向锁就是锁对象会记录获取了锁对象的当前线程的id,如果锁没有释放锁,这个时候有另一个线程需要进入,就会用线程id对比一下是不是当前线程如果不是则获取不到锁。 当等待的线程变多就会升级为自旋锁(在用户态进行,在CPU中进行自旋) 进一步升级为重量级锁–OS锁(在内核态进行,不占用CPU) 拓展 线程少,占用锁时间短采用自旋锁,线程多占用锁时间长用系统锁 三、volatile 防止指令重排序 public class Singleton { /* * 说明: * Object o = new Object(); * 此条语句不是原子性操作,并且是分三步进行的 * 1、申请地址空间 * 2、初始化 * 3、将地址赋值给变量o * 由于JVM存在指令重排机制一次1,2,3不一定会按顺序执行,如果在高并发情况下可能会有线程拿到还未进行初始化的对象 * */ private volatile Singleton instance = null; private Singleton(){ } public Singleton getInstance(){ if(instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } return instance; } } return instance; } }

保证被修饰变量线程间的可见性,底层是通过CPU的缓存一致性协议(MESI)完成的

public class MyThread extends Thread { /*此处不加关键字volatile线程thread1将一直在处在wile循环中,因为对主线程修改的flag不可见*/ private static volatile boolean flag = false; public void run() { while (!flag); } public static void main(String[] args) throws Exception { Thread thread1 = new MyThread(); thread1.start(); Thread.sleep(2000); flag = true; } } 码农JJ 原创文章 8获赞 5访问量 888 关注 私信 展开阅读全文
作者:码农JJ



java多线程 JAVA synchronized volatile 线程

需要 登录 后方可回复, 如果你还没有账号请 注册新账号