Java程序入口就是由JVM启动的main线程:

main线程又可以启动其他线程。当所有线程都运行结束时JVM退出,进程结束。

守护线程(Daemon):守护线程是为其他线程服务的线程,所有的非守护线程都执行完毕后,虚拟机才会退出。

守护线程的特点:不能持有资源(如打开文件等)

创建守护线程:

setDaemon(true);

下面来演示下,子线程中有死循环,而主线程退出了,子线程还没退出。

程序运行截图如下:

主线程已经退出,而子线程没有退出。

源码如下:

import java.text.SimpleDateFormat;
import java.util.Date;class MyThread1 extends Thread{@Overridepublic void run() {while (true) {Date date = new Date(System.currentTimeMillis());SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");System.out.println(formatter.format(date));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Main1 {public static void main(String[] args) throws InterruptedException {System.out.println("BEGIN");MyThread1 myThread1 = new MyThread1();myThread1.start();Thread.sleep(1000 * 3);System.out.println("OVER");}
}

加上守护线程后,即可在main函数退出后,页退出!

程序运行截图如下:

源码如下:

import java.text.SimpleDateFormat;
import java.util.Date;class MyThread1 extends Thread{@Overridepublic void run() {while (true) {Date date = new Date(System.currentTimeMillis());SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");System.out.println(formatter.format(date));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Main1 {public static void main(String[] args) throws InterruptedException {System.out.println("BEGIN");MyThread1 myThread1 = new MyThread1();myThread1.setDaemon(true);myThread1.start();Thread.sleep(1000 * 3);System.out.println("OVER");}
}

下面是线程同步相关的设置:

多个线程同时运行,线程调度由操作系统决定,程序本身无法决定。

如下多个线程同时读取共享数据时:

会出现问题,程序运行截图如下:

代码如下:

class AddThread extends Thread{@Overridepublic void run() {for(int i = 0; i < Main2.LOOP; i++){Main2.count += 1;}}
}class DecThread extends Thread{@Overridepublic void run() {for(int i = 0; i < Main2.LOOP; i++){Main2.count -= 1;}}
}public class Main2 {final static int LOOP = 10000;public static int count = 0;public static void main(String[] arg) throws InterruptedException {AddThread addThread = new AddThread();DecThread decThread = new DecThread();addThread.start();decThread.start();addThread.join();decThread.join();System.out.println(count);System.out.println("OVER");}
}

对共享数据进行写入时,必须要保证是原子操作

Java使用synchronized对一个对象进行加锁!

synchronized的缺陷:性能会下降;

synchronized的使用:

找出修改共享变量线程代码块;选择一个实例作为锁;使用synchronized(lockObject){...}

运行截图如下:

代码如下:

class AddThread3 extends Thread{@Overridepublic void run() {for(int i = 0; i < Main2.LOOP; i++){synchronized (Main3.LOCK) {Main2.count += 1;}}}
}class DecThread3 extends Thread{@Overridepublic void run() {for(int i = 0; i < Main2.LOOP; i++){synchronized (Main3.LOCK) {Main2.count -= 1;}}}
}public class Main3 {final static int LOOP = 10000;public static int count = 0;public static final Object LOCK = new Object();public static void main(String[] arg) throws InterruptedException {AddThread3 addThread = new AddThread3();DecThread3 decThread = new DecThread3();addThread.start();decThread.start();addThread.join();decThread.join();System.out.println(count);System.out.println("OVER");}
}

使用synchronized:不用担心异常!

public void add(int m){synchronized (obj){if(m < 0){throw new RuntimeException();}this.value += m;}//无论有无异常,都会在此释放
}

JVM规范定义了几种原子操作:

基本类型(long和double除外)赋值:int n = 100;

引用类型的赋值:List<String> list = anotherList;

下面是关于synchronized其他的写法

public synchronized void add(int n){count += n;total += n;
}public void add(int n){synchronized(this){count += n;total += n;}
}

上面这两个写法是等价的。

如果一个类被设计为允许多线程正确访问:这个类就是“线程安全”的(thread-safe)

如java.lang.StringBuffer就是线程安全的。

synchronized是可以重复使用的。如下:

public void add(int m){synchronized (lockA){this.value += m;synchronized (lockB){this.another += m;}//释放lockB}//释放lockA
}

这里要注意:不同线程获取多个不同对象的锁可能会导致死锁。

死锁形成的条件(注意了,不管是哪个编程语言都差不多):

两个线程各自持有不同的锁;

两个线程各自试图获取对方已持有的锁;

双方无限等待下去:导致死锁。

死锁发送后:没有任何机制能解除死锁;只能强制结束JVM进程。

如何避免死锁:线程获取锁的顺序要一致!

如下实例!

源码如下:

class SharedObject{final Object lockA = new Object();final Object lockB = new Object();int accountA = 1000;int accountB = 2000;public void a2b(int balance){synchronized (lockA){accountA -= balance;synchronized (lockB){accountB += balance;}}}public void b2a(int balance){synchronized (lockB){accountB -= balance;synchronized (lockA){accountA += balance;}}}
}class AThread extends Thread{@Overridepublic void run() {for(int i = 0; i < Main4.LOOP; i++){Main4.shared.a2b(1);System.out.println("ing...");}}
}class BThread extends Thread{@Overridepublic void run() {Main4.shared.b2a(1);for(int i = 0; i < Main4.LOOP; i++){System.out.println("ing...");}}
}public class Main4 {final static int LOOP = 100000;static SharedObject shared = new SharedObject();public static void main(String[] args) throws InterruptedException {Thread t1 = new AThread();Thread t2 = new AThread();t1.start();t2.start();t1.join();t2.join();System.out.println("OVER");}
}

这个代码是有死锁的但不一定发送:

原因是这样的:

此处只要把锁的先后改成一样的就可以了!

Java笔记-多线程中同步加锁相关相关推荐

  1. java笔记——多线程笔记

    目录 学习目标: 1.线程简介 普通方法调用和多线程的区别​编辑 Process(进程)与Thread(线程) 本章核心概念 2.线程创建 2.1 三种创建方式 2.2Thread(重点) 2.3Ru ...

  2. Java笔记(学习中。。)

    Java笔记 eclipse的使用 常用的dos指令 预备知识 基本语法 变量 关于字符型 关于String 进制转换 运算符 流程控制 数组 数组的内存解析: 数组的Arrays工具类 面向对象 对 ...

  3. Java:多线程(同步死锁、锁原子变量、线程通信、线程池)

    5,同步和死锁 5.1,线程同步 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象: 修饰一个方法,被修饰的方法称为同步方法,其作用 ...

  4. java笔记--关于线程同步(7种同步方式)

    关于线程同步(7种方式) --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3897440.html"谢谢-- 为何要使用同步? ...

  5. 11.1-全栈Java笔记:多线程技术的基本概念

    多线程是JAVA语言的重要特性,大量应用于网络编程.应用于服务器端程序的开发.以及最常见的UI界面底层原理.操作系统底层原理都大量使用了多线程. 我们可以流畅的点击软件或者游戏中的各种按钮,其实,底层 ...

  6. Java笔记-多线程相关

    ava多线程和C++里面的多线程有些地方不一样. 毕竟套了一个java虚拟机.对此记录下. Java语言内置多线程支持: 一个java程序实际上是一个JVM进程. JVM用一个主线程来执行main() ...

  7. Java笔记-多线程协调及ReentrantLock的使用

    这里使用wait/notify去协调线程. 感觉这个比C/C++里面信号量还要好用一点. 使用synchronized没有解决多线程协调问题 public synchronized String ge ...

  8. Java笔记-多线程之线程控制

    线程控制 我们已经知道了线程的调度,接下来我们就可以使用如下方法对象线程进行控制. 1.线程休眠 public static void sleep(long millis):让当前线程处于暂停状态,m ...

  9. java在SAE中使用的相关问题总结

    1.监听器问题 SAE需要加入监听器:详细地址参考http://jacobcookie.iteye.com/blog/1876798 2.关于jar包的问题 删了servlet的包,SAE中包含这些, ...

最新文章

  1. 2016030204 - git和github结合
  2. 手机端系统提交数据的创建时间验证的问题
  3. 前端面试---Vue部分考点梳理
  4. 第5章 Python 数字图像处理(DIP) - 图像复原与重建2 - 瑞利噪声
  5. JVM虚拟机-Class文件简介
  6. [转载] 朴素贝叶斯python实现预测_Python实现朴素贝叶斯分类器的方法详解
  7. python爬虫利器p_Python:网络爬虫相当利器
  8. 精通 JS正则表达式(转)
  9. Zookeeper中的ACL
  10. CSS 绘制一个时钟
  11. vim命令,保存文件,设置行号,退出vim,读入外部文件,一般模式下的查找与替换
  12. 修改CodeRunner快捷键
  13. endnotex9安装后使用方法_EndNoteX9个人安装说明.PDF
  14. 计算机专业该如何找实习工作?迷茫、不知所措的你值得一看~
  15. 国科大本科生9个月设计出处理器芯片 可运行Linux系统
  16. 从网上骂人言论看其浮躁无知的一面
  17. linux 全选 编辑文本_强烈推荐:Linux终端文本编辑器Micro
  18. OA系统管理项目工作内容
  19. 【244天】我爱刷题系列(3)
  20. Mysql 报错Duplicate entry '值' for key '字段名'的解决

热门文章

  1. jquery--选择器sizzle源码分析
  2. 加载exe的PE信息并输出相关PE信息的一段c++代码
  3. C 语言程序设计基础不好,想10天考国二C语言程序设计证书,可能吗?
  4. 为什么需要python?它在人工智能与机器学习的优势是什么?
  5. 我的程序都是这样命名的:openeim001
  6. 现代办公通讯手段对比分析
  7. 惊现飞鸽传书2009
  8. *printf()格式化串安全漏洞分析(下)
  9. b700a怎么连蓝牙_小身材有大功能,小米蓝牙耳机AirDots青春版初体验
  10. java集合按大小排序_JAVA中对List根据map某个key值从小到大顺序进行排序