/** * Updates {@code storedPermits} and {@code nextFreeTicketMicros} based on the current time. */ voidresync(long nowMicros){ // if nextFreeTicket is in the past, resync to now if (nowMicros > nextFreeTicketMicros) { storedPermits = min(maxPermits, storedPermits + (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros()); nextFreeTicketMicros = nowMicros; } }
-- 令牌桶算法: -- 1. 校验输入: local need_token = tonumber(ARGV[1]) local req_time = tonumber(ARGV[2]) iftype(need_token) ~= "number"ortype(req_time) ~= "number"then return0 end
-- 2. 校验redis: local key = KEYS[1] local info = redis.pcall("HMGET", key, "last_time", "cur_token_num", "max_token", "rate") local last_time = tonumber(info[1]) local cur_token_num = tonumber(info[2]) local max_token = tonumber(info[3]) local rate = tonumber(info[4])
fnmain() { let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); println!("count after creating a = {}", Rc::strong_count(&a)); let b = Cons(3, Rc::clone(&a)); println!("count after creating b = {}", Rc::strong_count(&a)); { let c = Cons(4, Rc::clone(&a)); println!("count after creating c = {}", Rc::strong_count(&a)); } println!("count after c goes out of scope = {}", Rc::strong_count(&a)); }
fnmain() { let handle = thread::spawn(|| { for i in1..10 { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } });
for i in1..5 { println!("hi number {} from the main thread!", i); thread::sleep(Duration::from_millis(1)); } handle.join().unwrap();// 阻塞等待子线程 }
子线程中可以捕获主线程的变量,获得所有权. 使用move,以免主线程把它drop了:
1 2 3 4 5 6 7 8 9 10 11
use std::thread;
fnmain() { let v = vec![1, 2, 3];
let handle = thread::spawn(move || { println!("Here's a vector: {:?}", v); });
handle.join().unwrap(); }
消息传递: channel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use std::thread; use std::sync::mpsc;
fnmain() { let (tx, rx) = mpsc::channel(); // tx: 发送者 // rx: 接收者 thread::spawn(move || { let val = String::from("hi"); tx.send(val).unwrap();// 单所有权,发送后不能再使用val });
let received = rx.recv().unwrap(); println!("Got: {}", received); }
mpsc: 多生产者、单消费者 recv: 阻塞接收 try_recv: 非阻塞接收,立即返回
这里之所以是多生产者,是因为可以把生产者无限克隆出去,然后发送消息:
1
let tx1 = mpsc::Sender::clone(&tx);
共享状态并发
互斥器(mutex)
rust中的锁是一种特殊的智能指针,通过重载drop trait来确保离开作用域的时候释放锁。
1 2 3 4 5 6 7 8 9
use std::sync::Mutex; fnmain() { let m = Mutex::new(5); { letmut num = m.lock().unwrap(); *num = 6; } println!("m = {:?}", m); }
let tup: (i32, f64, u8) = (500, 6.4, 1); let five_hundred = x.0;
数组:
1 2 3
let a = [1, 2, 3, 4, 5]; // 或: let a: [i32; 5] = [1, 2, 3, 4, 5];
函数
用fn声明.
1 2 3 4 5 6 7 8 9 10 11
fnmain() { another_function(5, 6); }
fnanother_function(x: i32, y: i32) { println!("The value of x is: {}", x); println!("The value of y is: {}", y); } fnfive() -> i32 { // 返回i32类型 5 }
表达式
表达式的结尾没有分号
1 2 3 4 5
let y = { let x = 3; x + 1// 没有分号 }; // y=4
循环
loop,while,for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
let result = loop { counter += 1; if counter == 10 { break counter * 2; } }; assert_eq!(result, 20); while index < 5 { println!("the value is: {}", a[index]); index = index + 1; } let a = [10, 20, 30, 40, 50]; for element in a.iter() { println!("the value is: {}", element); } for number in (1..4).rev() { println!("{}!", number); }
ownership 所有权
rust无需gc。 要学习的点包括: 借用、slice、内存布局。
所有权:管理堆数据
所有权的三大法则:
Rust中的每一个值都有一个被称为其 所有者(owner)的变量。
值有且只有一个所有者。
当所有者(变量)离开作用域,这个值将被丢弃。
创建一个堆上的变量:
1 2 3 4
{ let s = String::from("hello"); s.push_str(", world!"); // 追加 }// rust自动调用s的drop,回收内存(类似于free\RAII模式)
s的大小运行时可变,因此它显然分配在堆上。(栈每个slot大小相同)
浅拷贝、深拷贝、移动
rust对复杂类型默认是移动; 基本类型直接深拷贝。 rust没有浅拷贝、只有移动。
1 2 3 4 5 6 7 8 9 10 11 12
// 移动: let s1 = String::from("hello"); let s2 = s1; println!("{}, world!", s1); // fail,s1已经无效,被移动为s2了。 // 深拷贝: let s1 = String::from("hello"); let s2 = s1.clone(); println!("s1 = {}, s2 = {}", s1, s2); // 基本类型: let x = 5; let y = x; println!("x = {}, y = {}", x, y);
letmut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s;// 如果后续都用的话报错,两个变量都借用了s,而且都是可写,有竞态,在同一作用域内。 // 只读引用的话可以有多个: let r1 = &s; // no problem let r2 = &s; // no problem let r3 = &mut s; // BIG PROBLEM 有只读引用的时候,也不能再有可写引用
借用结束的话可以消除竞态:
1 2 3 4 5
letmut a = String::from("hello world"); let b = &a[0..4]; println!("{}", b); append_a(&mut a);// 这里没问题,因为b后面没有用到。 // println!("{}", b); // 这里会报错,因为b的作用域和a的有交叉。
悬挂指针
Rust 中编译器确保永远不会有悬挂指针。 构造悬挂指针:
1 2 3 4 5 6 7
fnmain() { let reference_to_nothing = dangle(); } fndangle() -> &String { let s = String::from("hello"); &s // 编译失败 }