大学网站 作风建设专题哪个网站做兼职有保障
大学网站 作风建设专题,哪个网站做兼职有保障,温州哪里有做网站的,wordpress 修改浏览量最近工作有用到一些多线程的东西#xff0c;之前吧#xff0c;有用到synchronized同步块#xff0c;不过是别人怎么用就跟着用#xff0c;并没有搞清楚锁的概念。最近也是遇到一些问题#xff0c;不搞清楚锁的概念#xff0c;很容易碰壁#xff0c;甚至有些时候自己连用…最近工作有用到一些多线程的东西之前吧有用到synchronized同步块不过是别人怎么用就跟着用并没有搞清楚锁的概念。最近也是遇到一些问题不搞清楚锁的概念很容易碰壁甚至有些时候自己连用没用对都不知道。今天把一些疑惑都解开了写篇文章分享给大家文章还算比较全面。当然可能有小宝鸽理解得不够深入透彻的地方如果说得不正确还望指出。看之前有必要跟某些猿友说一下如果看一遍没有看明白呢也没关系当是了解一下等真正使用到了再回头看。本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁。特别的是希望能帮大家理清一些概念。一、synchronized关键字synchronized关键字有如下两种用法1、 在需要同步的方法的方法签名中加入synchronized关键字。synchronized public void getValue() {System.out.println(getValue method thread name Thread.currentThread().getName() username username password password);}上面的代码修饰的synchronized是非静态方法如果修饰的是静态方法(static)含义是完全不一样的。具体不一样在哪里后面会详细说清楚。synchronized static public void getValue() {System.out.println(getValue method thread name Thread.currentThread().getName() username username password password);}2、使用synchronized块对需要进行同步的代码段进行同步。public void serviceMethod() {try {synchronized (this) {System.out.println(begin time System.currentTimeMillis());Thread.sleep(2000);System.out.println(end end System.currentTimeMillis());}} catch (InterruptedException e) {e.printStackTrace();}}上面的代码块是synchronized (this)用法还有synchronized (非this对象)以及synchronized (类.class)这两种用法这些使用方式的含义也是有根本的区别的。我们先带着这些问题继续往下看。二、Java中的对象锁和类锁小宝鸽似乎并没有办法用清晰简短的语言来描述对象锁和类锁的概念。即便能用简单的语句概况也会显得抽象。猿友们耐心看完自然会明白。之前网上有找一些相关资料有篇博客是这样描述的(看的是转载的原创连接我也不知道)一段synchronized的代码被一个线程执行之前他要先拿到执行这段代码的权限在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁)如果这个时候同步对象的锁被其他线程拿走了他(这个线程)就只能等了(线程阻塞在锁池等待队列中)。取到锁后他就开始执行同步代码(被synchronized修饰的代码)线程执行完同步代码后马上就把锁还给同步对象其他在锁池中等待的某个线程就可以拿到锁执行同步代码了。这样就保证了同步代码在统一时刻只有一个线程在执行。这段话除了最后一句讲得都是挺合理的。”这样就保证了同步代码在统一时刻只有一个线程在执行。”这句话显然不对synchronized并非保证同步代码同一时刻只有一个线程执行同步代码同一时刻应该可以有多个线程执行。上面提到锁这里先引出锁的概念。先来看看下面这些啰嗦而必不可少的文字。多线程的线程同步机制实际上是靠锁的概念来控制的。在Java程序运行时环境中JVM需要对两类线程共享的数据进行协调1)保存在堆中的实例变量2)保存在方法区中的类变量这两类数据是被所有线程共享的。(程序不需要协调保存在Java 栈当中的数据。因为这些数据是属于拥有该栈的线程所私有的。)这里插播一下广告关于JVM内存如果想了解可以看看博主的另外一篇文章方法区(Method Area)与Java堆一样是各个线程共享的内存区域它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分但是它却有一个别名叫做Non-Heap(非堆)目的应该是与Java堆区分开来。栈在Java中JVM中的栈记录了线程的方法调用。每个线程拥有一个栈。在某个线程的运行过程中如果有新的方法调用那么该线程对应的栈就会增加一个存储单元即帧(frame)。在frame中保存有该方法调用的参数、局部变量和返回地址。堆是JVM中一块可自由分配给对象的区域。当我们谈论垃圾回收(garbage collection)时我们主要回收堆(heap)的空间。Java的普通对象存活在堆中。与栈不同堆的空间不会随着方法调用结束而清空。因此在某个方法中创建的对象可以在方法调用结束之后继续存在于堆中。这带来的一个问题是如果我们不断的创建新的对象内存空间将最终消耗殆尽。在java虚拟机中每个对象和类在逻辑上都是和一个监视器相关联的。对于对象来说相关联的监视器保护对象的实例变量。对于类来说监视器保护类的类变量。(如果一个对象没有实例变量或者一个类没有变量相关联的监视器就什么也不监视。)为了实现监视器的排他性监视能力java虚拟机为每一个对象和类都关联一个锁。代表任何时候只允许一个线程拥有的特权。线程访问实例变量或者类变量不需锁。但是如果线程获取了锁那么在它释放这个锁之前就没有其他线程可以获取同样数据的锁了。(锁住一个对象就是获取对象相关联的监视器)类锁实际上用对象锁来实现。当虚拟机装载一个class文件的时候它就会创建一个java.lang.Class类的实例。当锁住一个对象的时候实际上锁住的是那个类的Class对象。一个线程可以多次对同一个对象上锁。对于每一个对象java虚拟机维护一个加锁计数器线程每获得一次该对象计数器就加1每释放一次计数器就减 1当计数器值为0时锁就被完全释放了。java编程人员不需要自己动手加锁对象锁是java虚拟机内部使用的。在java程序中只需要使用synchronized块或者synchronized方法就可以标志一个监视区域。当每次进入一个监视区域时java 虚拟机都会自动锁上对象或者类。三、synchronized关键字各种用法与实例看完了”二、Java中的对象锁和类锁”我们再来结合”一、synchronized关键字”里面提到的synchronized用法。事实上synchronized修饰非静态方法、同步代码块的synchronized (this)用法和synchronized (非this对象)的用法锁的是对象线程想要执行对应同步代码需要获得对象锁。synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类线程想要执行对应同步代码需要获得类锁。因此事实上synchronized关键字可以细分为上面描述的五种用法。本文的实例均来自于《Java多线程编程核心技术》这本书里面的例子。1、我们先看看非线程安全实例(Run.java)public class Run {public static void main(String[] args) {HasSelfPrivateNum numRef new HasSelfPrivateNum();ThreadA athread new ThreadA(numRef);athread.start();ThreadB bthread new ThreadB(numRef);bthread.start();}}class HasSelfPrivateNum {private int num 0;public void addI(String username) {try {if (username.equals(a)) {num 100;System.out.println(a set over!);Thread.sleep(2000);} else {num 200;System.out.println(b set over!);}System.out.println(username num num);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class ThreadA extends Thread {private HasSelfPrivateNum numRef;public ThreadA(HasSelfPrivateNum numRef) {super();this.numRef numRef;}Overridepublic void run() {super.run();numRef.addI(a);}}class ThreadB extends Thread {private HasSelfPrivateNum numRef;public ThreadB(HasSelfPrivateNum numRef) {super();this.numRef numRef;}Overridepublic void run() {super.run();numRef.addI(b);}}运行结果为a set over!b set over!b num200a num200修改HasSelfPrivateNum如下方法用synchronized修饰如下class HasSelfPrivateNum {private int num 0;synchronized public void addI(String username) {try {if (username.equals(a)) {num 100;System.out.println(a set over!);Thread.sleep(2000);} else {num 200;System.out.println(b set over!);}System.out.println(username num num);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}运行结果是线程安全的b set over!b num200a set over!a num100实验结论两个线程访问同一个对象中的同步方法是一定是线程安全的。本实现由于是同步访问所以先打印出a然后打印出b这里线程获取的是HasSelfPrivateNum的对象实例的锁——对象锁。2、多个对象多个锁就上面的实例我们将Run改成如下public class Run {public static void main(String[] args) {HasSelfPrivateNum numRef1 new HasSelfPrivateNum();HasSelfPrivateNum numRef2 new HasSelfPrivateNum();ThreadA athread new ThreadA(numRef1);athread.start();ThreadB bthread new ThreadB(numRef2);bthread.start();}}运行结果为a set over!b set over!b num200a num200这里是非同步的因为线程athread获得是numRef1的对象锁而bthread线程获取的是numRef2的对象锁他们并没有在获取锁上有竞争关系因此出现非同步的结果这里插播一下同步不具有继承性3、同步块synchronized (this)我们先看看代码实例(Run.java)public class Run {public static void main(String[] args) {ObjectService service new ObjectService();ThreadA a new ThreadA(service);a.setName(a);a.start();ThreadB b new ThreadB(service);b.setName(b);b.start();}}class ObjectService {public void serviceMethod() {try {synchronized (this) {System.out.println(begin time System.currentTimeMillis());Thread.sleep(2000);System.out.println(end end System.currentTimeMillis());}} catch (InterruptedException e) {e.printStackTrace();}}}class ThreadA extends Thread {private ObjectService service;public ThreadA(ObjectService service) {super();this.service service;}Overridepublic void run() {super.run();service.serviceMethod();}}class ThreadB extends Thread {private ObjectService service;public ThreadB(ObjectService service) {super();this.service service;}Overridepublic void run() {super.run();service.serviceMethod();}}运行结果begin time1466148260341end end1466148262342begin time1466148262342end end1466148264378这样也是同步的线程获取的是同步块synchronized (this)括号()里面的对象实例的对象锁这里就是ObjectService实例对象的对象锁了。需要注意的是synchronized (){}的{}前后的代码依旧是异步的4、synchronized (非this对象)我们先看看代码实例(Run.java)public class Run {public static void main(String[] args) {Service service new Service(xiaobaoge);ThreadA a new ThreadA(service);a.setName(A);a.start();ThreadB b new ThreadB(service);b.setName(B);b.start();}}class Service {String anyString new String();public Service(String anyString){this.anyString anyString;}public void setUsernamePassword(String username, String password) {try {synchronized (anyString) {System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 进入同步块);Thread.sleep(3000);System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 离开同步块);}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class ThreadA extends Thread {private Service service;public ThreadA(Service service) {super();this.service service;}Overridepublic void run() {service.setUsernamePassword(a, aa);}}class ThreadB extends Thread {private Service service;public ThreadB(Service service) {super();this.service service;}Overridepublic void run() {service.setUsernamePassword(b, bb);}}不难看出这里线程争夺的是anyString的对象锁两个线程有竞争同一对象锁的关系出现同步现在有一个问题一个类里面有两个非静态同步方法会有影响么答案是如果对象实例A线程1获得了对象A的对象锁那么其他线程就不能进入需要获得对象实例A的对象锁才能访问的同步代码(包括同步方法和同步块)。不理解可以细细品味一下5、静态synchronized同步方法我们直接看代码实例public class Run {public static void main(String[] args) {ThreadA a new ThreadA();a.setName(A);a.start();ThreadB b new ThreadB();b.setName(B);b.start();}}class Service {synchronized public static void printA() {try {System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 进入printA);Thread.sleep(3000);System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 离开printA);} catch (InterruptedException e) {e.printStackTrace();}}synchronized public static void printB() {System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 进入printB);System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 离开printB);}}class ThreadA extends Thread {Overridepublic void run() {Service.printA();}}class ThreadB extends Thread {Overridepublic void run() {Service.printB();}}运行结果线程名称为A在1466149372909进入printA线程名称为A在1466149375920离开printA线程名称为B在1466149375920进入printB线程名称为B在1466149375920离开printB两个线程在争夺同一个类锁因此同步6、synchronized (class)对上面Service类代码修改成如下class Service {public static void printA() {synchronized (Service.class) {try {System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 进入printA);Thread.sleep(3000);System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 离开printA);} catch (InterruptedException e) {e.printStackTrace();}}}public static void printB() {synchronized (Service.class) {System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 进入printB);System.out.println(线程名称为 Thread.currentThread().getName() 在 System.currentTimeMillis() 离开printB);}}}运行结果线程名称为A在1466149372909进入printA线程名称为A在1466149375920离开printA线程名称为B在1466149375920进入printB线程名称为B在1466149375920离开printB两个线程依旧在争夺同一个类锁因此同步需要特别说明对于同一个类A线程1争夺A对象实例的对象锁线程2争夺类A的类锁这两者不存在竞争关系。也就说对象锁和类锁互补干预内政静态方法则一定会同步非静态方法需在单例模式才生效但是也不能都用静态同步方法总之用得不好可能会给性能带来极大的影响。另外有必要说一下的是Spring的bean默认是单例的。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/87909.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!