同步代码块的作用:同步代码块里面的代码只能有一个线程进来,其他的线程需要在外面等待
同步代码块的格式:
Object obj = new Object(); synchronized (锁对象obj) { }任意对象都可以作为锁对象,(只要是一个对象)
同步代码块同步什么代码:包住操作共享资源的代码
同步方法的作用:方法中的代码都是被同步的
同步方法使用的锁:使用this作为锁
静态同步方法的锁: 类名.class作为锁
Lock接口作用
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作Lock和synchronized一样保证只有一个线程能够进入 // Lock lc = ...; // 创建一把锁 Lock lc = new ReentrantLock(); lc.lock(); // 获取锁 try { // 同步的代码 } finally { lc.unlock(); // 释放锁 }定义生产者类SetNameRun
class SetNameRun implements Runnable { //生产者类 Stu stu = null; public static int cnt; public SetNameRun(Stu stu) { this.stu = stu; } @Override public void run() { while(true) { synchronized (stu) { if(stu.name != null) { //生产者发现stu的名字不为空时就等待 try { stu.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //生产者发现stu的名字为空时就生产一个名字 "偶数" 或 "奇数" if((cnt & 1) == 0) stu.name = "偶数"; else stu.name = "奇数"; stu.age = cnt; System.out.printf("%s %s : %d\n", Thread.currentThread().getName(), stu.name, cnt); cnt ++; stu.notify(); //唤醒任意一个等待stu的线程 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } }创建消费者类
class GetNameRun implements Runnable { //消费者类 Stu stu = null; public GetNameRun(Stu stu) { this.stu = stu; } @Override public void run() { while(true) synchronized (stu) { if(stu.name == null) { //消费者发现stu没有名字就等待生产者生产 try { stu.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("%s : %s %d\n", Thread.currentThread().getName(), stu.name, stu.age); stu.name = null; stu.notify(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }完整代码
package Demo3; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Scanner; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Stu { public String name; int age; public Stu() { } public Stu(String name, int age) { this.name = name; this.age = age; } } class SetNameRun implements Runnable { Stu stu = null; public static int cnt; public SetNameRun(Stu stu) { this.stu = stu; } @Override public void run() { while(true) { synchronized (stu) { if(stu.name != null) { try { stu.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if((cnt & 1) == 0) stu.name = "偶数"; else stu.name = "奇数"; stu.age = cnt; System.out.printf("%s %s : %d\n", Thread.currentThread().getName(), stu.name, cnt); cnt ++; stu.notify(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class GetNameRun implements Runnable { Stu stu = null; public GetNameRun(Stu stu) { this.stu = stu; } @Override public void run() { while(true) synchronized (stu) { if(stu.name == null) { try { stu.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("%s : %s %d\n", Thread.currentThread().getName(), stu.name, stu.age); stu.name = null; stu.notify(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Main { public static final boolean debug = true; public static String INPATH = "C:\\Users\\majiao\\Desktop\\test.txt", OUTPATH = "C:\\Users\\majiao\\Desktop\\out.txt"; public static StreamTokenizer tok; public static BufferedReader cin; public static PrintWriter cout; public static long start_time = 0, out_time = 0; public static int n, m, K, Q, MAXN = (int)1e5+7, INF = 0x3f3f3f3f; public static byte buf[] = new byte[MAXN]; public static void main(String[] args) throws IOException { main_init(); if(debug) { start_time = System.currentTimeMillis(); } if(false) { System.setOut(new PrintStream(OUTPATH)); } Stu stu = new Stu(); SetNameRun set = new SetNameRun(stu); GetNameRun get = new GetNameRun(stu); Thread A = new Thread(set), B = new Thread(get); A.setName("生产"); B.setName("消费"); A.start(); B.start(); if(debug) { out_time = System.currentTimeMillis(); cout.printf("run time : %d ms\n", out_time-start_time); } cout.flush(); } public static void main_init() { try { if (debug) { cin = new BufferedReader(new InputStreamReader( new FileInputStream(INPATH))); } else { cin = new BufferedReader(new InputStreamReader(System.in)); } cout = new PrintWriter(new OutputStreamWriter(System.out)); // cout = new PrintWriter(OUTPATH); tok = new StreamTokenizer(cin); } catch (Exception e) { e.printStackTrace(); } } public static String next_str() { try { tok.nextToken(); if (tok.ttype == StreamTokenizer.TT_EOF) return null; else if (tok.ttype == StreamTokenizer.TT_NUMBER) { return String.valueOf((int)tok.nval); } else if (tok.ttype == StreamTokenizer.TT_WORD) { return tok.sval; } else return null; } catch (Exception e) { e.printStackTrace(); return null; } } public static int read_int() { String tmp_next_str = next_str(); return null==tmp_next_str ? -1 : Integer.parseInt(tmp_next_str); } public static long read_long() { return Long.parseLong(next_str()); } public static double read_double() { return Double.parseDouble(next_str()); } public static BigInteger read_big() { return new BigInteger(next_str()); } public static BigDecimal read_dec() { return new BigDecimal(next_str()); } }