线程安全:
当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的
synchronized:
可以在任意对象及方法上加锁,而加锁的这段代码称为"互斥区"或"临界区"
例子:
public class MyThread extends Thread{ private int count = 5 ; //synchronized加锁 public void run(){ count--; System.out.println(this.currentThread().getName() + " count = "+ count); } public static void main(String[] args) { MyThread myThread = new MyThread(); Thread t1 = new Thread(myThread,"t1"); Thread t2 = new Thread(myThread,"t2"); Thread t3 = new Thread(myThread,"t3"); Thread t4 = new Thread(myThread,"t4"); Thread t5 = new Thread(myThread,"t5"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } } 输出结果:t2 count = 3
t1 count = 3
t4 count = 2
t3 count = 1
t5 count = 0
count值并没有按照顺序去减
下面 将run方法加上synchronized
public class MyThread extends Thread{ private int count = 5 ; //synchronized加锁 public synchronized void run(){ count--; System.out.println(this.currentThread().getName() + " count = "+ count); } public static void main(String[] args) { MyThread myThread = new MyThread(); Thread t1 = new Thread(myThread,"t1"); Thread t2 = new Thread(myThread,"t2"); Thread t3 = new Thread(myThread,"t3"); Thread t4 = new Thread(myThread,"t4"); Thread t5 = new Thread(myThread,"t5"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } } 输出结果:t1 count = 4 t3 count = 3 t4 count = 2 t2 count = 1 t5 count = 0
结论分析:
当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排对是按照CPU分配的先后顺序而定的),一个线程想要执行synchronized修饰的方法里的代码:
1 尝试获得锁
2 如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,
而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)
对象锁和类级别锁
关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁,所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock)
在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。
列子
public class MultiThread { private int num = 0; /** static */ public synchronized void printNum(String tag){ try { if(tag.equals("a")){ num = 100; System.out.println("tag a, set num over!"); Thread.sleep(1000); } else { num = 200; System.out.println("tag b, set num over!"); } System.out.println("tag " + tag + ", num = " + num); } catch (InterruptedException e) { e.printStackTrace(); } } //注意观察run方法输出顺序 public static void main(String[] args) { //俩个不同的对象 final MultiThread m1 = new MultiThread(); final MultiThread m2 = new MultiThread(); Thread t1 = new Thread(new Runnable() { @Override public void run() { m1.printNum("a"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { m2.printNum("b"); } }); t1.start(); t2.start(); } 结果 tag a, set num over! tag b, set num over! tag b, num = 200 tag a, num = 100
结果分析: 线程m1 m2都执行了run方法,如果m1线程调到run方法时,获得了对象锁,m2等待m1执行完才执行,结果应该是 :
tag a, set num over! tag a, num = 100 tag b, set num over! tag b, num = 200
其实不然,m1 m2 是2个对象,有2把锁,没有冲突,所以都可以执行,可以使用类级别锁,输出结果会按照顺序
public class MultiThread { private static int num = 0; /** static */ public static synchronized void printNum(String tag){ try { if(tag.equals("a")){ num = 100; System.out.println("tag a, set num over!"); Thread.sleep(1000); } else { num = 200; System.out.println("tag b, set num over!"); } System.out.println("tag " + tag + ", num = " + num); } catch (InterruptedException e) { e.printStackTrace(); } } //注意观察run方法输出顺序 public static void main(String[] args) { //俩个不同的对象 final MultiThread m1 = new MultiThread(); final MultiThread m2 = new MultiThread(); Thread t1 = new Thread(new Runnable() { @Override public void run() { m1.printNum("a"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { m2.printNum("b"); } }); t1.start(); t2.start(); } 结果: tag a, set num over! tag a, num = 100 tag b, set num over! tag b, num = 200
结果分析:在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类),无论创建几个对象,调用printNum()方法,获取的都是类级别锁
结论:
关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁,所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),
在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。
对象锁的同步和异步
同步: synchronized
同步的概念就是共享,我们要牢牢记住共享这2个字,如果不是“共享”资源,就没必要进行同步
异步:
异步的概念就是独立,相互之间不受任何制约,就好像学习http的时候,在页面发起ajax请求,还可以继续浏览和操作页面的内容,二者之间没有任何关系
public class MyObject { //同步方法 public synchronized void method1(){ try { System.out.println(Thread.currentThread().getName()); Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } /** 异步方法,没有任何锁的机制就是异步方法*/ public void method2(){ System.out.println(Thread.currentThread().getName()); } }
区别:
method1异步方法多个线程需要排队的方法,而method2同步方法多个线程可以并发的访问
例子
public class MyObject { public synchronized void method1(){ try { System.out.println(Thread.currentThread().getName()); Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } /** synchronized */ public void method2(){ System.out.println(Thread.currentThread().getName()); } public static void main(String[] args) { final MyObject mo = new MyObject(); Thread t1 = new Thread(new Runnable() { @Override public void run() { mo.method1(); } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { mo.method2(); } },"t2"); t1.start(); t2.start(); } } 结果: 同时输出 t1 t2,没有等待4秒输出t2
分析:
t1线程先持有object对象的Lock锁,t2线程可以以异步的方式调用对象中的非synchronized修饰的方法
t1线程先持有object对象的Lock锁,t2线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步
相关推荐
### C#多线程基础详解 #### 知识点一:多线程概念与优势 在C#中,多线程是指一个程序中同时执行多个线程的能力。一个线程是程序执行的基本单位,每个线程都有自己的指令指针、栈和局部变量,但共享相同的内存空间...
这个"JAVA多线程基础演练DEMO"提供了一些基础示例,帮助开发者更好地理解和掌握多线程的基本概念和用法。以下将详细讲解Java多线程的相关知识点: 1. **线程的创建** - **继承Thread类**:创建一个新类,继承自`...
通过学习和掌握这些多线程基础知识,开发者能够编写出更加高效、稳定的并发程序,提升软件系统的性能和用户体验。同时,对多线程深入理解也有助于应对面试中的技术考察,为职业生涯的晋升铺平道路。
**多线程基础** 多线程是指在一个进程中可以同时运行多个独立的执行流,每个执行流被称为一个线程。在MFC中,我们可以使用`CWinThread`类来创建和管理线程。`CWinThread`是MFC对Windows API中的`_beginthreadex`和`...
本教程将深入探讨C#中的多线程基础,包括创建线程、线程同步与通信、线程池以及线程安全等内容。 一、线程创建 在C#中,有两种主要方式来创建线程:使用`System.Threading.Thread`类和使用`System.Threading.Tasks...
在IT行业中,多线程是程序并发执行的一种方式,它极大地提高了系统资源的利用率和程序...在学习过程中,可以参考"多线程基础总结01.bmp"和"多线程基础总结01.mmap"等文件,它们可能提供了更为详细和直观的结构化知识。
本压缩包“多线程基础与基于多线程的简单聊天室”提供了对多线程技术的实践理解和二次开发的基础。以下是关于这个主题的详细知识点: 1. **多线程的概念**:多线程是指在一个程序中同时执行多个不同的线程,每个...
C#多线程是编程中的重要概念,尤其在开发高性能...总的来说,理解和掌握C#多线程基础知识对于编写高效、健壮的程序至关重要。在实际开发中,应合理利用多线程,注意线程安全,避免潜在的问题,提升软件的稳定性和性能。
以下是一些关于C#多线程的基础知识: 1. **线程的创建**:在C#中,可以使用`System.Threading.Thread`类来创建新的线程。通过实例化`Thread`类并提供一个代表新线程执行的委托,即可启动新线程。例如,`new ...
Java多线程是Java编程中的一个...以上只是Java多线程基础知识的一部分,深入学习还包括线程池的配置与优化、线程安全的设计模式、并发工具类的使用等。理解和掌握这些知识点对于编写高效、稳定的多线程程序至关重要。
### VC 线程基础知识总结 #### 一、线程概念与重要性 在计算机科学领域,线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。程序员可以通过多线程技术,实现并发执行任务,...
《新手学C#》这本书提供了一个很好的起点,帮助新手快速掌握线程基础知识。在这个压缩包文件"一看就懂线程代码"中,很可能包含了以下关键知识点: 1. **线程的创建与启动**:在C#中,可以使用`System.Threading....
Java线程基础是Java编程中的重要组成部分,尤其在多核处理器和并发编程需求日益增长的今天,理解并掌握线程的使用至关重要。IBM提供了一系列的Java线程教程,旨在帮助开发者深入理解Java线程的基本概念、创建与管理...
Java多线程基础篇讲解是针对初学者设计的教程,旨在用简洁明了的语言帮助学习者更容易理解多线程的概念和应用。多线程编程在现代计算机系统中扮演着重要角色,尤其在CPU主频发展遇到瓶颈的情况下,通过超线程技术和...
通过深入学习和实践这些Java线程基础知识,你可以有效地编写出高效、安全的多线程程序。记住,理解线程的原理和掌握同步机制是关键,这将有助于解决复杂的并发问题。阅读"Java线程.pdf"文档,你将获得更详细、全面的...
多线程从基础讲起,包括线程基础、线程属性、互斥量、共享内存、条件变量。
头歌java多线程基础 “头歌”是一个在线教育平台,提供包括Java在内的多种编程语言的在线学习资源和课程。Java多线程基础是学习Java编程中非常重要的一部分,它涉及到如何同时运行多个任务,以充分利用现代多核...
"多线程基础代码.rar"这个压缩包文件很可能是包含了一些关于多线程编程的基础示例代码,用于帮助初学者理解和实践多线程技术。 多线程允许一个应用程序同时执行多个不同的任务,每个任务被称为一个线程。在Java、C#...
Java并发编程中的线程基础是理解多线程编程的关键,它涵盖了从线程的创建到管理,再到线程间通信的全过程。多线程编程在处理高性能和高响应性的应用程序时至关重要,因为它允许程序在单个进程中同时执行多个任务,...
Java多线程基础知识 Java多线程基础知识是Java编程语言中的一项重要技术,用于提高程序的执行效率和响应速度。在这里,我们将详细介绍Java多线程基础知识的相关概念和技术。 一、程序、进程和线程 程序(Program...