Multi-threaded LinkedList Implementation I am learning to write a multi-threaded linked list class implementation with basic functionality such as push to front or back, pop_back and read. I came up with this implementation:

#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;mutex&gt;
std::mutex m;
template&lt;class T&gt;
class Node{
    public:
    T data;
    Node* next;
    Node(T data):data(data),next(NULL){}
};
template&lt;class T&gt;
class List{
  Node&lt;T&gt; *head;
  public:
  List():head(NULL){}
  List(const List&lt;T&gt;&amp;)=default;               //default copy constructor
  List&amp; operator =(const List&lt;T&gt;&amp;)=default;   //default assignment
  List(List&lt;T&gt;&amp;&amp;)=default;                    //default move constructor
  List&amp; operator =(List&lt;T&gt;&amp;&amp;)=default;        //default move assignment
  void push_front(T val){                    //push data to front
    std::lock_guard&lt;std::mutex&gt; lock(m);
    Node&lt;T&gt;* temp=new Node&lt;T&gt;(val);
      if(head==NULL)
        head=temp;
      else{

          temp-&gt;next=head;
          head=temp;
      }
  }
  void pop_back(){                      //pop from back
      std::lock_guard&lt;std::mutex&gt; lock(m);
      Node&lt;T&gt;* cur=head;
      while(cur-&gt;next-&gt;next)
      cur = cur-&gt;next;
      Node&lt;T&gt;* temp=cur-&gt;next;
      delete(temp);
      cur-&gt;next=NULL;
  }
  T front(){                 //return front of Linkedlist
      if(head!=NULL)
      return head-&gt;data;
      return -1;
  }
  void push_back(T val){                    //push at back
      std::lock_guard&lt;std::mutex&gt; lock(m);
      Node&lt;T&gt;* temp=new Node&lt;T&gt;(val);
      if(head==NULL)
        head=temp;
      else{
          Node&lt;T&gt;* cur=head;
          while(cur-&gt;next)
          cur = cur-&gt;next;
          cur-&gt;next=temp;
      }
  }
  int size(){               //return size
      int size=0;
      Node&lt;T&gt;* cur=head;
      while(cur){
        size++;
        cur=cur-&gt;next;
      }
      return size;
  }
  void display(){            //read from linked list
      std::lock_guard&lt;std::mutex&gt; lock(m);
      Node&lt;T&gt;* cur=head;
      while(cur){
          std::cout&lt;&lt;cur-&gt;data&lt;&lt;" ";
          cur = cur-&gt;next;
      }
      std::cout&lt;&lt;"\n";
  }
  ~List(){
    Node&lt;T&gt;* current = head;
    Node&lt;T&gt;* next;
    while (current != NULL) {
        next = current-&gt;next;
        delete current;
        current = next;
    }
  }
};


But, I am not very sure if I covered it right. Please share some opinions on how to make it perfect.
Also, I am targeting C++11, so please throw some pointers/suggestions in that area also.

In particular, I am looking for is answers to these questions:


Is this a correct approach for acquiring mutex in push() and display(), in a multi-threaded environment?
How can I prioritize the read/delete/write operations. For example, suppose 1 thread is displaying the data and another thread comes which wants to pop_back from the data. How do I make the changes so that my 2nd thread gets the priority while 1st thread was using my node. 
I have not much worked with C++11 — I just started it few months ago — so I would like to know what more I should have in my class.
In case there are any possible bugs in this code, please let me know that too.
About the code:


List&amp; operator =(const List&lt;T&gt;&amp;)=default; and List(const List&lt;T&gt;&amp;)=default; provide excellent opportunity to get double delete with 100% chance of success.
Your linked list required data to be copyable and it copies it on usage. It is bad, since now you cannot store data like std::unique_ptr that are not copyable. Also it is inefficient as it will have to copy large data structures like std::vector instead of moving their internal data around. Utilize std::move in functions like push_back/push_front.
Functions front()/back() should return data by reference so user can modify them. Also you ought to implement their const versions that return data by const reference (or by value for trivial enough data types).
std::list stores also the size of the list so the function call is lazy unlike your implementation. People generally assume that size() is a fast operation which is not the case in your implementation.
Normally in a linked-list you store both head and tail as otherwise all operations regarding the other end are ridiculously slow.
std::cout is not exactly thread safe. It doesn't crash or cause malfunctions but it might can mingle the characters you print. In a multi-threaded environment you need a logger.
Wait... your linked-list doesn't provide any options for iterating over elements. Only adding / deleting / exploring elements at the head/tail and even those are slow. You need iterators or something. One important aspect of a linked list is ability to move elements from one list to another efficiently. This functionality doesn't exist in this implementation.
Your mutex m is shared across all your linked lists-instances and types. If you want any sensible implementation of multi-threaded linked with mutexes list you ought to privately store a std::unique_ptr&lt;std::mutex&gt; for each instance of the linked-list.
Honestly, I don't know why you want to use a linked list or implement one - it is one of the slowest and most inefficient data structures.


In general, I don't think that it is a good idea to make a thread-safe linked-list. Make a concurrent linked-list at most I'd say (I not too familiar on this topic as far as I am aware it is still being researched). Just use std::list and have an associated mutex nearby so whenever user wants to do something with the list - they have to lock the mutex. It might be annoying to write and relying on the user to use it right is problematic but frequently user needs to make composite operations (several in a row without interruptions) which will result in program errors if another users locks the list in between these operations and does something with it.