在java语言中存在两种内建的synchronized语法:synchronized语句和synchronized方法。synchronized将并行改为串行,当然会影响程序的执行效率,执行速度会受到影响。其次synchronized操作线程的堵塞,也就是由操作系统控制CPU的内核进行上下文的切换,这个切换本身也是耗时的。所以使用synchronized关键字会降低程序的运行效率。
三个售票窗口同时出售20张票
- public class Test1 {
- public static void main(String[] args) {
- for(int i=1;i<=3;i++) {
- new 售票线程(i+"号窗口").start();
- }
- }
- }
-
-
- class 售票线程 extends Thread{
- private String name;
- private static Integer count=20;//票池,static保证多个线程对象共享一个票池
- private static final String aaa="bbbb";
- public 售票线程(String name) {
- this.name = name;
- }
- @Override
- public void run() {
- while(count>0) {
- // System.out.println(this.name+count+"开始售票");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (aaa) {
- if(count>0) {
- System.out.println(this.name+"售出第 "+count+" 号票");
- count--;
- // System.out.println(this.name+":"+count);
- }else {
- System.out.println(this.name+"票已售尽");
- }
- // System.out.println(this.name+count+"结束售票");
- }
- }
- }
- }
Synchronized用于实现同步处理,保证共享数据的安全性
数据有安全性问题的原因:1、共享数据 2、修改数据Synchronized相对于volatile是重量级的线程安全的方法,可以保证3大特性:原子性、可见性、有序性
synchronized将并行改为串行
-用于静态方法,锁对象为当前类public synchronized static void pp(){}
-用于非静态方法,锁对象为当前类的对象
public synchronized void pp(){}
-用于代码块,锁对象为指定的对象 该对象可以自定义
synchronized(obj){}
- import java.util.concurrent.locks.Lock;
-
- //同步代码块
- public class A {
- public static void main(String[] args) {
- for(int i=1;i<=3;i++) {
- new MyThread(i+"号窗口").start();
- }
- }
- }
-
- class MyThread extends Thread{
- private String name;
- private static int counter=20;
- private static final String LOCK="bbbb";
-
- public MyThread(String name) {
- this.name=name;
- }
-
- @Override
- public void run() {
- while(counter>0) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (LOCK) {//锁的数量一定要比资源少,要把资源锁住,用name不可以,因为name是3个窗口,不能锁住,锁有一把;只要是引用类型都可以,
- if(counter>0) {
- System.out.println(this.name+"售出第"+counter+"号票");
- synchronized (LOCK) {
- counter--;
- }
- System.out.println(this.name+":"+counter);
- }else {
- System.out.println(this.name+":"+"票已售尽");
- }
- }
- }
- }
- }
- public class A2 {
- public static void main(String[] args) throws Exception {
- NumOper no=new NumOper(100);
- Thread[] th=new Thread[4];
- for (int i = 0; i < 2; i++) {
- th[i*2]=new Thread(() -> {
- for(int k=0;k<50;k++) {
- no.add();
- }
- });
- th[i*2].start();
- th[i*2+1]=new Thread(() -> {
- for(int k=0;k<50;k++) {
- no.sub();
- }
- });
- th[i*2+1].start();
- }
- for(Thread tmp:th)
- tmp.join();
- System.out.println("Main:"+no.getNum());
- }
- }
-
- /*
- * 以new出来的NumOper对象充当锁,当前对象内的synchronized方法在不同线程调用时互斥,
- * 但是可以直接访问非synchronized方法
- *
- * 注意synchronized允许持有锁的线程重入
- */
- class NumOper {
- private int num;
-
- public NumOper(int num) {//synchronized不能添加到构造器上
- this.num = num;
- }
-
- public synchronized void add() {
- System.out.println(Thread.currentThread() + "Thread......begin" + this.num);
- this.num++;
- // sub();
- System.out.println(Thread.currentThread() + "Thread......end" + this.num);
- }
-
- public synchronized void sub() {
- System.out.println(Thread.currentThread() + "Thread......begin" + this.num);
- this.num--;
- System.out.println(Thread.currentThread() + "Thread......end" + this.num);
- }
-
- public int getNum() {
- return this.num;
- }
- }
统计指定类的创建次数 ,代码如下:
- public class A3 {
- public static void main(String[] args) {
- for(int i=0;i<5;i++) {
- new Thread(()->{
- for(int k=0;k<10;k++) {
- new S3();
- }
- }).start();
- }
- try {
- Thread.sleep(10000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(S3.getCounter());//
- }
- }
-
- class S3{
- private static int counter=0;
-
- public S3() {
- add();
- }
-
- private synchronized static void add() {//static 不可以用this
- System.out.println(Thread.currentThread()+"开始创建操作"+counter);
- counter++;
- System.out.println(Thread.currentThread()+"完成创建操作"+counter);
- }
- public static int getCounter() {
- return counter;
- }
- }
使用类锁,所以不管new了多少个对象,都可以得到互斥的效果
- public class A4 {
- public static void main(String[] args) {
- new Thread(()->{
- for(int i=0;i<20;i++) {
- S4 ss=new S4();
- ss.pp1();
- }
- }).start();
- new Thread(()->{
- for(int i=0;i<20;i++) {
- S4 ss=new S4();
- ss.pp1();
- }
- }).start();
- }
- }
-
- class S4{
- public synchronized static void pp1() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public void pp2() {}
- }
使用的是对象锁,所以只能new一个对象,都可以得到互斥的效果。如果创建多个则不能达到互斥目的
- public class A41 {
- public static void main(String[] args) {
- S41 ss=new S41();
- new Thread(()->{
- // S41 ss=new S41();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- ss.pp2();
- }
- }).start();
- new Thread(()->{
- // S41 ss=new S41();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- ss.pp2();
- }
- }).start();
- }
- }
- //类S4为锁对象
- class S41{
- public synchronized static void pp1() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized void pp2() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized void pp3() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- }
使用的是不同的锁,所以thread0和thread1不能达到互斥的效果。
- public class A42 {
- public static void main(String[] args) {
- S42 ss=new S42();
- new Thread(()->{
- // S41 ss=new S41();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- // ss.pp2();//非static方法 --对象锁 ss
- ss.pp3();
- }
- }).start();
- new Thread(()->{
- // S41 ss=new S41();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- ss.pp1();//static方法 --类锁 S42.class
- ss.pp4();
- }
- }).start();
- }
- }
- //类S4为锁对象
- class S42{
- public synchronized static void pp1() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized void pp2() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized static void pp3() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized static void pp4() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- }
锁对象不一样会导致锁不住,一个是类锁,一个是对象锁
- public class A44 {
- public static void main(String[] args) {
- S44 ss=new S44();
- new Thread(()->{
- // S44 ss=new S44();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- // ss.pp2();//非static方法 --对象锁 ss
- ss.pp3();
- }
- }).start();
- new Thread(()->{
- // S44 ss=new S44();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- ss.pp2();//非static方法 --对象锁 ss
- }
- }).start();
- new Thread(()->{
- // S44 ss=new S44();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- ss.pp1();//static方法 --类锁 S42.class
- }
- }).start();
- new Thread(()->{
- // S44 ss=new S44();
- for(int i=0;i<20;i++) {
- // S41 ss=new S41();
- ss.pp4();
- }
- }).start();
- }
- }
- //类S4为锁对象
- class S44{
- public synchronized static void pp1() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized void pp2() {
- System.out.println(Thread.currentThread()+"...begin..."+Thread.currentThread().getName());
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end..."+Thread.currentThread().getName());
- }
- public synchronized static void pp3() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- public synchronized static void pp4() {
- System.out.println(Thread.currentThread()+"...begin...");
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread()+"...end...");
- }
- }