Linux 多線程

来源:https://www.cnblogs.com/chu-yi/archive/2018/11/03/9843179.html
-Advertisement-
Play Games

1,概念: 進程:一個正在執行的程式,他是資源分配的最小單位。進程中的事情語言按照一定順序逐一進行 線程:又稱輕量級線程,程式執行的最小單位,系統獨立調度和分派CPU的基本單位,他是進程中一個實體,一個進程中可以有多個線程,這些線程共用進程的所有資 源,線程本身只包含一點必不可少的資源。 併發:指在 ...


  

  

1,概念:

  進程:一個正在執行的程式,他是資源分配的最小單位。進程中的事情語言按照一定順序逐一進行

  線程:又稱輕量級線程,程式執行的最小單位,系統獨立調度和分派CPU的基本單位,他是進程中一個實體,一個進程中可以有多個線程,這些線程共用進程的所有資                源,線程本身只包含一點必不可少的資源。

  併發:指在同一時刻,只能有執行一條指令,但多個線程指令被快速輪換執行,使得巨集觀上具有多個進程同時執行的效果 。   (看起來同時發生,針對單核

  並行:指在同一時刻,有多條指令在多個處理器上同時執行。 (真正的同時發生

  同步:彼此有依賴關係的調用不應該“同時發生”,而同步就是阻止那些“同時發生”的事情

  非同步:與同步相對,任何兩個彼此獨立的操作時非同步的,它表明事情獨立發生

 

多線程的優勢:

  1)在多處理器中開發程式的並行性

  2)在等待慢速IO操作時,程式可以執行其他操作,提高併發性

  3)模塊化的編程,能更清晰的表達程式中獨立事件的關係,結構清晰

  4)占用較少的系統資源

  多線程不一定要多處理器

 

線程創造 獲取ID,生命周期
線程式控制制 終止、連接、取消、發送信號、清除操作
線程同步 互斥量、讀寫鎖、條件變數
線程高級控制 一次性初始化、線程屬性、同步屬性、私有數據、安全的fork()

 

2,線程的基本控制

  創建新線程

    線程ID

  線程 進程
標識符類型 pthread_t pid_t
獲取ID pthread_seif() getpid()
創建 pthread_create() fork()

      pthread_t : 結構體    unsigned long int   (linux 中提高移植性)        /usr/include/bits/pthreadtypes.h

    

       獲取線程ID : pthread_self()

         頭文件: #include <pthread.h>

         函數:    pthread_t  pthread_seif();

         返回值 :  線程ID

       編譯鏈接時需要用到線程庫  -pthread         ::gcc -pthread  (用到線程都要用)

 

    創建線程:ptnread_create()

        函數:  int  ptnread_create ( ptnread_t *restrict tidp, const ptnread_attr_t *restrict attr , void *(*start_routine)(void *) , void *restrict arg)

        參數:  第一個參數: 新線程的ID,如果成功則新線程的ID回填充到tipe 指向的記憶體

            第二個參數 : 線程屬性 (調整策略,繼承性,分離性...)

             第三個參數 : 回調函數  (新線程要執行的函數)

             第四個參數  : 回調函數的參數

        返回值 : 成功   0  ;  失敗則返回錯誤碼  

        編譯時需要連接庫  -pthread   主線程結束後必須有延時讓其創建新線程,不然主進程直接被返回。方法用延時或者 下述2

 

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <sys/types.h>
 6 #include <string.h>
 7 void print_id(char *s)
 8 {
 9    pid_t pid;
10    pthread_t tid;
11 
12    pid = getpid();
13    tid = pthread_self();
14 
15   printf("%s pid is %u,the tid is %lu\n",s,pid,tid);
16 
17 }
18 
19 void *thread_fun (void *arg)
20 {
21    print_id(arg);
22    return (void *)0;
23 }
24 
25 int main()
26 {
27    pthread_t ntid;
28    int err;
29 
30    err = pthread_create (&ntid, NULL , thread_fun ,"new thread");
31 
32    if(err!=0)
33    {
34         printf("create new thread failure\n");
35         return 0;
36     }
37 //      printf("create new thread sucess\n");
38         print_id("main thread:");
39         sleep(2);
40         return 0;
41 }
42 ~  
43 
44 結果:
45 main thread: pid is 2833,the tid is 3076491008
46 new thread pid is 2833,the tid is 3076488000
進程創建    

 

  線程的生命周期

  

      1,當C程式運行時,首先運行main()函數;線上程代碼中,這個特殊的執行流被稱為初始線程或者主線程。可以在初始線程中做任何普通線程可以做的事情

      2,主線程的特殊性在於,它在main() 函數返回的時候,會導致進程的結束,進程內所有的線程也將會結束。為了避免這種情況,需要在主線程中調用  pthread_exit() 函數,這樣進程就會等所有線程結束時才終止。

      3,主線程接收參數的方式是通過argc 和argv[] ;而普通線程只有一個參數 void*

      4,絕大多數情況下,主線程在預設堆棧上運行,這個堆棧可以 延長,而普通線程的堆棧會收到限制,一旦溢出就會出錯

 

      5,主線程是隨著進程的創建而創建,其他線程可以通過調用函數來創建  ,主要為 pthread_create();

      6,新線程可能在當前線程從函數  pthread_cteate ()  返回之前就已經開始運行,甚至可能在返回之前就已經運行完畢

 1 #include "stdio.h"
 2 #include "pthread.h"
 3 #include "stdlib.h"
 4 #include "unistd.h"
 5 #include "sys/types.h"
 6 #include "string.h"
 7 
 8 struct student
 9 {
10    int age;
11    char name[20];
12    char id[5];
13 };
14 
15 void *thread(void *s)
16 {
17 
18    printf("student age is %d,name is %s,id is %s\n",((struct student *)s)->age,((struct student *)s)->name,((struct student *)s)->id);
19    return (void *)0;
20 
21 }
22 
23 
24 int main(int argc,char *argv[])
25 {
26 
27     pthread_t tid;
28     int err;
29 
30 
31      struct student stu;
32       stu.age =20;
33       memcpy(stu.name , "zhangsan" , 20);
34       memcpy(stu.id , "0001" , 5);
35     err = pthread_create(&tid , NULL , thread , (void *)(&stu));
36    if(err != 0)
37       {
38 
39         printf("creat new thread failure\n");
40         return 0;
41 
42         }
43     int i;
44         for(i=0;i<argc;i++)
45         {
46              printf("main thread args is %s\n",argv[i]);
47 
48         }
49         sleep(1);
50         return 0;
51 
52 }
53 ~ 
54 結果:
55 root@ubuntu:/home/xiaozhao# gcc -pthread b.c -o b
56 root@ubuntu:/home/xiaozhao# ./b 21  32 42
57 main thread args is ./b
58 main thread args is 21
59 main thread args is 32
60 main thread args is 42
61 student age is 20,name is zhangsan,id is 0001
驗證主進程的特殊

 

 1 #include "stdio.h"
 2 #include "pthread.h"
 3 #include "stdlib.h"
 4 #include "unistd.h"
 5 #include "sys/types.h"
 6 #include "string.h"
 7 
 8 void *thread(void *s)
 9 {
10    int i=0;
11         while(1)
12 {
13    if(i%2 ==1)
14 
15    printf("new thread is %d\n",i);
16     i++;
17    sleep(1);
18 }
19    return (void *)0;
20 
21 }
22 
23 
24 int main(int argc,char *argv[])
25 {
26 
27     pthread_t tid;
28     int err;
29 
30     err = pthread_create(&tid , NULL , thread , "new thread");
31    if(err != 0)
32       {
33 
34         printf("creat new thread failure\n");
35         return 0;
36       }
37     int i=0;
38         while(i<10)
39         {
40         if(i%2 == 0)
41         printf( "main thread is %d\n",i);
42         i++;
43         sleep(1);
44         }
45         return 0;
46 
47 }
48 
49 
50 結果:
51 root@ubuntu:/home/xiaozhao# ./c
52 main thread is 0
53 new thread is 1
54 main thread is 2
55 new thread is 3
56 main thread is 4
57 new thread is 5
58 main thread is 6
59 new thread is 7
60 main thread is 8
61 new thread is 9
62 
63 
64 
65 
66 註意:
67  主線程迴圈結束,新線程也被結束;而新線程迴圈結束,不會影響主線程
68     
主線程和新線程交替列印奇偶

 

   

    線程的四個狀態

         就緒: 當線程剛被創建處於就緒狀態,或者當線程解除阻塞以後也會處於就緒狀態。就緒的線程在等待一個可用的處理器,當一個運行的線程被搶占時,它立即又回到就緒狀態

         運行 :線程正在運行,在多核系統中,可能同時又多個線程在運行

         阻塞: 線程在等待處理器意外的其他條件(試圖加鎖一個已經被鎖住的互斥量,等待某個條件變數,調用singwait 等待尚未發生的信號,執行無法完成的I\O信號,由於記憶體錯誤)

            終止: 線程從啟動函數中返回,或者調用 pthread_exit() 函數,或者被取消

 

    回收

           線程的分離屬性:

          分離一個正在運行的線程並不影響它,僅僅是通知當前系統該線程結束的時,其所屬的資源可以回收,一個沒有被分離的線程在終止時會保留其虛擬記憶體,包括他們的堆棧和其他系統資源,有時這種線程被稱為“僵屍進程”。創建線程時預設時非分離的

          如果線程具有分離屬性,線程終止時會被立刻回收,回收將釋放掉所有線上程終止時未被釋放的系統資源和進程資源,包括保存線程返回值的記憶體空間、堆棧、保存寄存器的記憶體空間等

          終止被分離的線程會釋放所有的系統資源,但是必須釋放有該線程占有的程式資源。由malloc() 或 mmap()  分配的記憶體可以在任何時候由任何線程釋放,條件變數、互斥量、信號燈可以由任何線程銷毀,只要他們被解鎖了或者沒有線程等待,但是只有互斥量的主人才能解鎖它,所以線上程終止前,需要解鎖互斥量

 

*********************************************************************************************************************************

 

  線程終止

    1, 如果進程中的任意一個線程調用了exit() , _Exit ,_exit , 那麼整個進程就會終止

    2,不終止進程的退出方式:

      普通的單個線程有以下三種方式退出,不會終止進程:

  •   從啟動歷程中返回,返回值是線程的退出碼    return
  •        線程可以被同一進程中的其他線程取消
  •        線程調用pthread_exit(void *rval) 函數,rval 是退出碼
 1 #include "stdio.h"
 2 #include "pthread.h"
 3 #include "stdlib.h"
 4 #include "unistd.h"
 5 #include "sys/types.h"
 6 #include "string.h"
 7 
 8 void *thread_fun (void *s)
 9 {
10   if(strcmp("1",(char *)s)==0)
11              return (void *)1;
12 
13   if(strcmp("2",(char *)s)==0)
14                 pthread_exit((void *)2);
15 
16   if(strcmp("3",(char *)s)==0)
17                exit(3);
18 }
19 
20 
21 int main(int argc, char *argv[])
22 {
23      pthread_t tid;
24      int err;
25 
26      err = pthread_create (&tid , NULL , thread_fun , (void *)argv[1]);
27      if (err !=0)
28     {
29       printf("create new thread failure\n");
30        return 0;
31     }
32       sleep(1);
33       printf("my is main thread\n");
34       return 0;
35 
36 }
37 結果:
38 root@ubuntu:/home/xiaozhao# ./d 1
39 my is main thread
40 root@ubuntu:/home/xiaozhao# ./d 2
41 my is main thread
42 root@ubuntu:/home/xiaozhao# ./d 3
43 root@ubuntu:/home/xiaozhao# 
44 
45 
46 說明:exit()會直接導致進程退出,而前兩種不會
三種退出方式

 

 

  線程連接(一個進程等待另一個進程完成在結束)

      int  pthread_join (pthread_t tid ,  void **rval)

  •       調用該函數的線程會一直阻塞,直到指定的線程tid 調用  pthread_exit () ; 從啟動歷程返回或者被取消
  •                       參數tid 就是指定線程的ID
  •                       參數ravl  是指定線程的返回碼,如果線程被取消,那麼ravl 被置為  PTHREAD_CANCELED
  •                       該函數調用成功會返回0,失敗返回錯誤碼

 

      調用pthread_join 會使指定的線程處於分離狀態,如果指定線程已經處於分離狀態,那麼調用就會失敗

      pthread_detach () 可以分離一個線程,線程可以自己分離自己

      int pthread_datach (pthread_t  thread);

        成功返回0 ;  失敗返回錯誤碼

 

 1 #include "apb.h"
 2 
 3 void *thread_fun1 (void *s)
 4 {
 5  printf("my is new thread1\n");
 6  return (void *)1;
 7 
 8 }
 9 
10 void *thread_fun2 (void *s)
11 {
12 
13  printf("my is new thread2\n");
14  pthread_detach(pthread_self());
15  pthread_exit((void *)2);
16 }
17 
18 int main()
19 {
20    int err1,err2;
21    pthread_t tid1,tid2;
22    void *rval1,*rval2;
23 
24   
25    err1 = pthread_create (&tid1 , NULL , thread_fun1 , NULL );
26    sleep(1);
27    err2 = pthread_create (&tid2 , NULL , thread_fun2 , NULL );
28    sleep(1);
29    if( err1 || err2 )
30         {
31           printf("create new thread failure\n");
32           return 0;
33         }
34 
35    printf("my is main thread\n");
36    printf("join rval1 is %d\n",pthread_join(tid1,&rval1));
37    printf("join rval2 is %d\n",pthread_join(tid2,&rval2));
38 
39    printf("thread1 exit is %d\n",(int )rval1);
40     printf("thread2 exit is %d\n",(int )rval2);
41 
42 
43 return 0;
44 }
45 ~   
46 
47 結果:
48 my is new thread1
49 my is new thread2
50 my is main thread
51 join rval1 is 0
52 join rval2 is 22
53 thread1 exit is 1
54 thread2 exit is -1216983040
55 
56 問題:
57 如果創建之後不加延時,線程二會比線程一早完成,輸出早。。目前不知原因及解決辦法
58 my is main thread
59 my is new thread2
60 my is new thread1
61 join rval1 is 0
62 join rval2 is 22
63 thread1 exit is 1
64 thread2 exit is -1216983040
連接,分離

 

 

     線程取消

    取消函數

      int  pthread_cancel (pthread_t tid);

      取消tid指定的線程,成功返回0.但是取消只是發送一個請求,並不意味著等待線程終止,而且發送成功也不意味著tid一定會終止。

 

    取消狀態 

      取消狀態就是線程對取消信號的處理方式,忽略或者響應。線程創建時預設響應取消信號

      int  pthread_setcancelstate (int state , int *oldstate);

        設置本線程對cancel 信號的反應,state有兩種值 :  PTHREAD_CANCEL_ENABLE(預設)和PTHREAD_CANCEL_DISABLE。。分別表示收到信號後設為CANCLED狀態和忽略CANCEL信號 繼續運行;old_state 如果不為NULL ,則存入原來的CANCEL 狀態以便恢復

 

    取消類型

      取消類型時線程對取消信號的響應方式,立即取消或者延時取消。線程創建時預設為延時取消

        int  pthread_setcanceltype (int type , int *oldtype);

      設置本線程取消動作的執行時機,type由兩種取值: PTHREAD_CANCEL_DEFFERED   和   PTHREAD_CANCEL_ASYCHRONOUS  ,  僅當cancel  狀態 為ENABLE時有效,分別表示收到信號後繼續運行至下一個取消點再退出,和 立即執行取消動作 (退出);  oldtype  如果不為NULL ,則存入運來的取消動作類型值。

 

       取消點

      取消一個線程,他通常需要被取消線程的配合。線程在很多時候會查看自己是否由取消請求。如果有,就主動退出,這些查看是否有取消的地方成為取消點

         很多地方都是包含取消點,包括 pthread_join() , pthread_teacancel() , 等等大多數會阻塞的系統調用

  1 線程被取消
  2 #include "apb.h"
  3 
  4 void *thread_fun (void *s)
  5 {
  6 int stateval;
  7 stateval = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE , NULL);
  8 if (stateval != 0)
  9 {
 10   printf("set cancel state failure\n");
 11 }
 12 printf("my is new thread\n");
 13 sleep(4);
 14 
 15 printf("about to cancel\n");
 16 stateval  = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE , NULL);
 17 printf("first cancel point\n");
 18 printf("secong cancel point\n");
 19 return (void *)20;
 20 
 21 
 22 }
 23 
 24 
 25 
 26 int main()
 27 {
 28   pthread_t tid;
 29    int err,cval;
 30    int jval;
 31    void *rval;
 32 
 33    err = pthread_create (&tid , NULL , thread_fun , NULL);
 34    if (err != 0)
 35     {
 36       printf("create new thread failure\n");
 37       return 0;
 38     }
 39     sleep(2);
 40     cval = pthread_cancel(tid);
 41    if(cval !=0)
 42     {
 43       printf("cancel thread failure\n");
 44     }
 45    jval = pthread_join(tid, &rval);
 46 
 47      printf("cancel rval is %d\n",(int )rval);
 48     return 0; 
 49 
 50 
 51 }
 52 
 53 結果:
 54 my is new thread
 55 about to cancel
 56 first cancel point
 57 cancel rval is -1
 58 
 59 
 60 線程忽略取消信號
 61 
 62 #include "apb.h"
 63 
 64 void *thread_fun (void *s)
 65 {
 66 int stateval;
 67 stateval = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE , NULL);
 68 if (stateval != 0)
 69 {
 70   printf("set cancel state failure\n");
 71 }
 72 printf("my is new thread\n");
 73 sleep(4);
 74 
 75 printf("about to cancel\n");
 76 stateval  = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE , NULL);
 77 printf("first cancel point\n");
 78 printf("secong cancel point\n");
 79 return (void *)20;
 80 
 81 
 82 }
 83 
 84 
 85 
 86 int main()
 87 {
 88   pthread_t tid;
 89    int err,cval;
 90    int jval;
 91    void *rval;
 92 
 93    err = pthread_create (&tid , NULL , thread_fun , NULL);
 94    if (err != 0)
 95     {
 96       printf("create new thread failure\n");
 97       return 0;
 98     }
 99     sleep(2);
100     cval = pthread_cancel(tid);
101    if(cval !=0)
102     {
103       printf("cancel thread failure\n");
104     }
105    jval = pthread_join(tid, &rval);
106 
107      printf("cancel rval is %d\n",(int )rval);
108     return 0; 
109 
110 
111 }
112 結果:
113 
114 my is new thread
115 about to cancel
116 
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • “導航屬性”是實體框架用得算是比較頻繁的概念。 首先,它是類型成員,其次,他是屬性,這不是 F 話,而是明確它的本質。那麼,什麼場景下會用到導航屬性呢?重點就落在“導航”一詞上了,當實體 A 需要引用實體 B 時,實體 A 中需要公開一個屬性,通過這個屬性,能找到關聯的實體 B。 又或者,X 實體表 ...
  • 一:問題場景 在一次項目開發中,項目中已使用了Autofac.在新需求中要用到Quatrz.Net.在任務中使用註入方法,確始終無法使用註入的方法,經過千百次的度娘,終於找到瞭解決辦法!吐槽下度娘真心不好用~~~ 二:解決問題 1:需要下載Autofac的擴展包 https://github.com ...
  • 結果:左連接 一對一 .Take()方法 由此看出 使用.Take(1)方法在多表關聯後可以實現與主表一對一的關係數據來;根據業務需要也實現特定N的條數。 ...
  • 一、Ubuntu訪問Windows共用文件夾 1、對需要共用文件夾右擊->屬性->共用 2、選擇要與其共用的用戶,選擇好用戶點擊有點添加按鈕添加,然後點擊下方的共用按鈕 3、完成共用 4、成功共用後可以在電腦管理查看已共用文件夾 5、Windows還需要進行一些設置,保證共用成功,控制面板->網路 ...
  • 決定開始複習Linux系統編程,這次我不再折騰Linux下的各種工具,直接使用VS2017進行代碼編寫與調試。 |配置項|值| | | | |VM|VMware® Workstation 15 Pro| |OS|CentOS 7 x86_64 Minimal 1804| |HD|單文件模式| |ME ...
  • 1. gpedit.msc 組策略 2. sndrec32 錄音機 3. Nslookup IP地址偵測器 4. explorer 打開資源管理器 5. logoff 註銷命令 6. tsshutdn 60秒倒計時關機命令 7. lusrmgr.msc 本機用戶和組 8. services.msc ...
  • ubuntu的16.04 18.04有lvm的功能(安裝的時候的選項),能在磁碟空間用完的時候,無縫增加一個磁碟進去。因為linux系統只有一個盤,所以是非常方便,不會有windows加1個磁碟要進行數據遷移,每次擴容C盤啊等等的問題 這個博客是在18.04 上實驗過的,本人已經在這台機子上擴容過兩 ...
  • swapon 在指定的設備上啟用交換分區,使用的設備或文件由專用文件參數提供。它可以是”-L label”或”-U UUID”,以指示一個設備的標簽或UUID。對swapon的調用通常發生在系統引導腳本中,使所有交換設備都可用,因此分頁和交換活動交叉在多個設備和文件之間。 此命令的適用範圍:RedH ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...